diff --git a/OsmAnd-java/.classpath b/OsmAnd-java/.classpath new file mode 100644 index 0000000000..7b0914ce10 --- /dev/null +++ b/OsmAnd-java/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/OsmAnd-java/.gitignore b/OsmAnd-java/.gitignore new file mode 100644 index 0000000000..ba077a4031 --- /dev/null +++ b/OsmAnd-java/.gitignore @@ -0,0 +1 @@ +bin diff --git a/OsmAnd-java/.project b/OsmAnd-java/.project new file mode 100644 index 0000000000..e7cfa33984 --- /dev/null +++ b/OsmAnd-java/.project @@ -0,0 +1,30 @@ + + + OsmAnd-java + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + + + android + 2 + OSMAND_TRUNK/android/OsmAnd/gen + + + + + OSMAND_TRUNK + $%7BPARENT-2-PROJECT_LOC%7D + + + diff --git a/OsmAnd-java/.settings/org.eclipse.jdt.core.prefs b/OsmAnd-java/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..8000cd6ca6 --- /dev/null +++ b/OsmAnd-java/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/OsmAnd-java/build.xml b/OsmAnd-java/build.xml new file mode 100644 index 0000000000..a8876aae1f --- /dev/null +++ b/OsmAnd-java/build.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + list is ${lib.list} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd-java/libs/bsh-core-2.0b4.jar b/OsmAnd-java/libs/bsh-core-2.0b4.jar new file mode 100644 index 0000000000..a1b8e47288 Binary files /dev/null and b/OsmAnd-java/libs/bsh-core-2.0b4.jar differ diff --git a/OsmAnd-java/libs/bzip2-20090327.jar b/OsmAnd-java/libs/bzip2-20090327.jar new file mode 100644 index 0000000000..5a0f290a07 Binary files /dev/null and b/OsmAnd-java/libs/bzip2-20090327.jar differ diff --git a/OsmAnd-java/libs/commons-logging-1.1.1.jar b/OsmAnd-java/libs/commons-logging-1.1.1.jar new file mode 100644 index 0000000000..1deef144cb Binary files /dev/null and b/OsmAnd-java/libs/commons-logging-1.1.1.jar differ diff --git a/OsmAnd-java/libs/gnu-trove-osmand.jar b/OsmAnd-java/libs/gnu-trove-osmand.jar new file mode 100644 index 0000000000..1bdfd836e0 Binary files /dev/null and b/OsmAnd-java/libs/gnu-trove-osmand.jar differ diff --git a/OsmAnd-java/libs/icu4j-49_1.jar b/OsmAnd-java/libs/icu4j-49_1.jar new file mode 100644 index 0000000000..ed1950c2b5 Binary files /dev/null and b/OsmAnd-java/libs/icu4j-49_1.jar differ diff --git a/OsmAnd-java/libs/json-20090211.jar b/OsmAnd-java/libs/json-20090211.jar new file mode 100644 index 0000000000..ef29094093 Binary files /dev/null and b/OsmAnd-java/libs/json-20090211.jar differ diff --git a/OsmAnd-java/libs/junidecode-0.1.jar b/OsmAnd-java/libs/junidecode-0.1.jar new file mode 100644 index 0000000000..7c79c879e5 Binary files /dev/null and b/OsmAnd-java/libs/junidecode-0.1.jar differ diff --git a/OsmAnd-java/libs/kxml2-2.3.0.jar b/OsmAnd-java/libs/kxml2-2.3.0.jar new file mode 100644 index 0000000000..647095222a Binary files /dev/null and b/OsmAnd-java/libs/kxml2-2.3.0.jar differ diff --git a/OsmAnd-java/libs/simple-logging.jar b/OsmAnd-java/libs/simple-logging.jar new file mode 100644 index 0000000000..89d3a05766 Binary files /dev/null and b/OsmAnd-java/libs/simple-logging.jar differ diff --git a/OsmAnd-java/libs/tuprolog.jar b/OsmAnd-java/libs/tuprolog.jar new file mode 100644 index 0000000000..529887697a Binary files /dev/null and b/OsmAnd-java/libs/tuprolog.jar differ diff --git a/OsmAnd-java/src/com/google/protobuf/AbstractMessage.java b/OsmAnd-java/src/com/google/protobuf/AbstractMessage.java new file mode 100644 index 0000000000..faf0980407 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/AbstractMessage.java @@ -0,0 +1,714 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; + +/** + * A partial implementation of the {@link Message} interface which implements + * as many methods of that interface as possible in terms of other methods. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class AbstractMessage extends AbstractMessageLite + implements Message { + @Override +@SuppressWarnings("unchecked") + public boolean isInitialized() { + // Check that all required fields are present. + for (final FieldDescriptor field : getDescriptorForType().getFields()) { + if (field.isRequired()) { + if (!hasField(field)) { + return false; + } + } + } + + // Check that embedded messages are initialized. + for (final Map.Entry entry : + getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + for (final Message element : (List) entry.getValue()) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (!((Message) entry.getValue()).isInitialized()) { + return false; + } + } + } + } + + return true; + } + + @Override + public final String toString() { + return TextFormat.printToString(this); + } + + @Override +public void writeTo(final CodedOutputStream output) throws IOException { + final boolean isMessageSet = + getDescriptorForType().getOptions().getMessageSetWireFormat(); + + for (final Map.Entry entry : + getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + if (isMessageSet && field.isExtension() && + field.getType() == FieldDescriptor.Type.MESSAGE && + !field.isRepeated()) { + output.writeMessageSetExtension(field.getNumber(), (Message) value); + } else { + FieldSet.writeField(field, value, output); + } + } + + final UnknownFieldSet unknownFields = getUnknownFields(); + if (isMessageSet) { + unknownFields.writeAsMessageSetTo(output); + } else { + unknownFields.writeTo(output); + } + } + + private int memoizedSize = -1; + + @Override +public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + final boolean isMessageSet = + getDescriptorForType().getOptions().getMessageSetWireFormat(); + + for (final Map.Entry entry : + getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + if (isMessageSet && field.isExtension() && + field.getType() == FieldDescriptor.Type.MESSAGE && + !field.isRepeated()) { + size += CodedOutputStream.computeMessageSetExtensionSize( + field.getNumber(), (Message) value); + } else { + size += FieldSet.computeFieldSize(field, value); + } + } + + final UnknownFieldSet unknownFields = getUnknownFields(); + if (isMessageSet) { + size += unknownFields.getSerializedSizeAsMessageSet(); + } else { + size += unknownFields.getSerializedSize(); + } + + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object other) { + if (other == this) { + return true; + } + if (!(other instanceof Message)) { + return false; + } + final Message otherMessage = (Message) other; + if (getDescriptorForType() != otherMessage.getDescriptorForType()) { + return false; + } + return getAllFields().equals(otherMessage.getAllFields()) && + getUnknownFields().equals(otherMessage.getUnknownFields()); + } + + @Override + public int hashCode() { + int hash = 41; + hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (53 * hash) + getAllFields().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + return hash; + } + + // ================================================================= + + /** + * A partial implementation of the {@link Message.Builder} interface which + * implements as many methods of that interface as possible in terms of + * other methods. + */ + @SuppressWarnings("unchecked") + public static abstract class Builder + extends AbstractMessageLite.Builder + implements Message.Builder { + // The compiler produces an error if this is not declared explicitly. + @Override + public abstract BuilderType clone(); + + @Override + public BuilderType clear() { + for (final Map.Entry entry : + getAllFields().entrySet()) { + clearField(entry.getKey()); + } + return (BuilderType) this; + } + + @Override + public BuilderType mergeFrom(final Message other) { + if (other.getDescriptorForType() != getDescriptorForType()) { + throw new IllegalArgumentException( + "mergeFrom(Message) can only merge messages of the same type."); + } + + // Note: We don't attempt to verify that other's fields have valid + // types. Doing so would be a losing battle. We'd have to verify + // all sub-messages as well, and we'd have to make copies of all of + // them to insure that they don't change after verification (since + // the Message interface itself cannot enforce immutability of + // implementations). + // TODO(kenton): Provide a function somewhere called makeDeepCopy() + // which allows people to make secure deep copies of messages. + + for (final Map.Entry entry : + other.getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + if (field.isRepeated()) { + for (final Object element : (List)entry.getValue()) { + addRepeatedField(field, element); + } + } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + final Message existingValue = (Message)getField(field); + if (existingValue == existingValue.getDefaultInstanceForType()) { + setField(field, entry.getValue()); + } else { + setField(field, + existingValue.newBuilderForType() + .mergeFrom(existingValue) + .mergeFrom((Message)entry.getValue()) + .build()); + } + } else { + setField(field, entry.getValue()); + } + } + + mergeUnknownFields(other.getUnknownFields()); + + return (BuilderType) this; + } + + @Override + public BuilderType mergeFrom(final CodedInputStream input) + throws IOException { + return mergeFrom(input, ExtensionRegistry.getEmptyRegistry()); + } + + @Override + public BuilderType mergeFrom( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final UnknownFieldSet.Builder unknownFields = + UnknownFieldSet.newBuilder(getUnknownFields()); + while (true) { + final int tag = input.readTag(); + if (tag == 0) { + break; + } + + if (!mergeFieldFrom(input, unknownFields, extensionRegistry, + this, tag)) { + // end group tag + break; + } + } + setUnknownFields(unknownFields.build()); + return (BuilderType) this; + } + + /** + * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder, + * ExtensionRegistryLite, Message.Builder)}, but parses a single field. + * Package-private because it is used by GeneratedMessage.ExtendableMessage. + * @param tag The tag, which should have already been read. + * @return {@code true} unless the tag is an end-group tag. + */ + static boolean mergeFieldFrom( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final Message.Builder builder, + final int tag) throws IOException { + final Descriptor type = builder.getDescriptorForType(); + + if (type.getOptions().getMessageSetWireFormat() && + tag == WireFormat.MESSAGE_SET_ITEM_TAG) { + mergeMessageSetExtensionFromCodedStream( + input, unknownFields, extensionRegistry, builder); + return true; + } + + final int wireType = WireFormat.getTagWireType(tag); + final int fieldNumber = WireFormat.getTagFieldNumber(tag); + + final FieldDescriptor field; + Message defaultInstance = null; + + if (type.isExtensionNumber(fieldNumber)) { + // extensionRegistry may be either ExtensionRegistry or + // ExtensionRegistryLite. Since the type we are parsing is a full + // message, only a full ExtensionRegistry could possibly contain + // extensions of it. Otherwise we will treat the registry as if it + // were empty. + if (extensionRegistry instanceof ExtensionRegistry) { + final ExtensionRegistry.ExtensionInfo extension = + ((ExtensionRegistry) extensionRegistry) + .findExtensionByNumber(type, fieldNumber); + if (extension == null) { + field = null; + } else { + field = extension.descriptor; + defaultInstance = extension.defaultInstance; + if (defaultInstance == null && + field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + throw new IllegalStateException( + "Message-typed extension lacked default instance: " + + field.getFullName()); + } + } + } else { + field = null; + } + } else { + field = type.findFieldByNumber(fieldNumber); + } + + boolean unknown = false; + boolean packed = false; + if (field == null) { + unknown = true; // Unknown field. + } else if (wireType == FieldSet.getWireFormatForFieldType( + field.getLiteType(), + false /* isPacked */)) { + packed = false; + } else if (field.isPackable() && + wireType == FieldSet.getWireFormatForFieldType( + field.getLiteType(), + true /* isPacked */)) { + packed = true; + } else { + unknown = true; // Unknown wire type. + } + + if (unknown) { // Unknown field or wrong wire type. Skip. + return unknownFields.mergeFieldFrom(tag, input); + } + + if (packed) { + final int length = input.readRawVarint32(); + final int limit = input.pushLimit(length); + if (field.getLiteType() == WireFormat.FieldType.ENUM) { + while (input.getBytesUntilLimit() > 0) { + final int rawValue = input.readEnum(); + final Object value = field.getEnumType().findValueByNumber(rawValue); + if (value == null) { + // If the number isn't recognized as a valid value for this + // enum, drop it (don't even add it to unknownFields). + return true; + } + builder.addRepeatedField(field, value); + } + } else { + while (input.getBytesUntilLimit() > 0) { + final Object value = + FieldSet.readPrimitiveField(input, field.getLiteType()); + builder.addRepeatedField(field, value); + } + } + input.popLimit(limit); + } else { + final Object value; + switch (field.getType()) { + case GROUP: { + final Message.Builder subBuilder; + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + subBuilder.mergeFrom((Message) builder.getField(field)); + } + input.readGroup(field.getNumber(), subBuilder, extensionRegistry); + value = subBuilder.build(); + break; + } + case MESSAGE: { + final Message.Builder subBuilder; + if (defaultInstance != null) { + subBuilder = defaultInstance.newBuilderForType(); + } else { + subBuilder = builder.newBuilderForField(field); + } + if (!field.isRepeated()) { + subBuilder.mergeFrom((Message) builder.getField(field)); + } + input.readMessage(subBuilder, extensionRegistry); + value = subBuilder.build(); + break; + } + case ENUM: + final int rawValue = input.readEnum(); + value = field.getEnumType().findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // drop it. + if (value == null) { + unknownFields.mergeVarintField(fieldNumber, rawValue); + return true; + } + break; + default: + value = FieldSet.readPrimitiveField(input, field.getLiteType()); + break; + } + + if (field.isRepeated()) { + builder.addRepeatedField(field, value); + } else { + builder.setField(field, value); + } + } + + return true; + } + + /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */ + private static void mergeMessageSetExtensionFromCodedStream( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final Message.Builder builder) throws IOException { + final Descriptor type = builder.getDescriptorForType(); + + // The wire format for MessageSet is: + // message MessageSet { + // repeated group Item = 1 { + // required int32 typeId = 2; + // required bytes message = 3; + // } + // } + // "typeId" is the extension's field number. The extension can only be + // a message type, where "message" contains the encoded bytes of that + // message. + // + // In practice, we will probably never see a MessageSet item in which + // the message appears before the type ID, or where either field does not + // appear exactly once. However, in theory such cases are valid, so we + // should be prepared to accept them. + + int typeId = 0; + ByteString rawBytes = null; // If we encounter "message" before "typeId" + Message.Builder subBuilder = null; + FieldDescriptor field = null; + + while (true) { + final int tag = input.readTag(); + if (tag == 0) { + break; + } + + if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) { + typeId = input.readUInt32(); + // Zero is not a valid type ID. + if (typeId != 0) { + final ExtensionRegistry.ExtensionInfo extension; + + // extensionRegistry may be either ExtensionRegistry or + // ExtensionRegistryLite. Since the type we are parsing is a full + // message, only a full ExtensionRegistry could possibly contain + // extensions of it. Otherwise we will treat the registry as if it + // were empty. + if (extensionRegistry instanceof ExtensionRegistry) { + extension = ((ExtensionRegistry) extensionRegistry) + .findExtensionByNumber(type, typeId); + } else { + extension = null; + } + + if (extension != null) { + field = extension.descriptor; + subBuilder = extension.defaultInstance.newBuilderForType(); + final Message originalMessage = (Message)builder.getField(field); + if (originalMessage != null) { + subBuilder.mergeFrom(originalMessage); + } + if (rawBytes != null) { + // We already encountered the message. Parse it now. + subBuilder.mergeFrom( + CodedInputStream.newInstance(rawBytes.newInput())); + rawBytes = null; + } + } else { + // Unknown extension number. If we already saw data, put it + // in rawBytes. + if (rawBytes != null) { + unknownFields.mergeField(typeId, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(rawBytes) + .build()); + rawBytes = null; + } + } + } + } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) { + if (typeId == 0) { + // We haven't seen a type ID yet, so we have to store the raw bytes + // for now. + rawBytes = input.readBytes(); + } else if (subBuilder == null) { + // We don't know how to parse this. Ignore it. + unknownFields.mergeField(typeId, + UnknownFieldSet.Field.newBuilder() + .addLengthDelimited(input.readBytes()) + .build()); + } else { + // We already know the type, so we can parse directly from the input + // with no copying. Hooray! + input.readMessage(subBuilder, extensionRegistry); + } + } else { + // Unknown tag. Skip it. + if (!input.skipField(tag)) { + break; // end of group + } + } + } + + input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG); + + if (subBuilder != null) { + builder.setField(field, subBuilder.build()); + } + } + + @Override + public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { + setUnknownFields( + UnknownFieldSet.newBuilder(getUnknownFields()) + .mergeFrom(unknownFields) + .build()); + return (BuilderType) this; + } + + /** + * Construct an UninitializedMessageException reporting missing fields in + * the given message. + */ + protected static UninitializedMessageException + newUninitializedMessageException(Message message) { + return new UninitializedMessageException(findMissingFields(message)); + } + + /** + * Populates {@code this.missingFields} with the full "path" of each + * missing required field in the given message. + */ + private static List findMissingFields(final Message message) { + final List results = new ArrayList(); + findMissingFields(message, "", results); + return results; + } + + /** Recursive helper implementing {@link #findMissingFields(Message)}. */ + private static void findMissingFields(final Message message, + final String prefix, + final List results) { + for (final FieldDescriptor field : + message.getDescriptorForType().getFields()) { + if (field.isRequired() && !message.hasField(field)) { + results.add(prefix + field.getName()); + } + } + + for (final Map.Entry entry : + message.getAllFields().entrySet()) { + final FieldDescriptor field = entry.getKey(); + final Object value = entry.getValue(); + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + int i = 0; + for (final Object element : (List) value) { + findMissingFields((Message) element, + subMessagePrefix(prefix, field, i++), + results); + } + } else { + if (message.hasField(field)) { + findMissingFields((Message) value, + subMessagePrefix(prefix, field, -1), + results); + } + } + } + } + } + + private static String subMessagePrefix(final String prefix, + final FieldDescriptor field, + final int index) { + final StringBuilder result = new StringBuilder(prefix); + if (field.isExtension()) { + result.append('(') + .append(field.getFullName()) + .append(')'); + } else { + result.append(field.getName()); + } + if (index != -1) { + result.append('[') + .append(index) + .append(']'); + } + result.append('.'); + return result.toString(); + } + + // =============================================================== + // The following definitions seem to be required in order to make javac + // not produce weird errors like: + // + // java/com/google/protobuf/DynamicMessage.java:203: types + // com.google.protobuf.AbstractMessage.Builder< + // com.google.protobuf.DynamicMessage.Builder> and + // com.google.protobuf.AbstractMessage.Builder< + // com.google.protobuf.DynamicMessage.Builder> are incompatible; both + // define mergeFrom(com.google.protobuf.ByteString), but with unrelated + // return types. + // + // Strangely, these lines are only needed if javac is invoked separately + // on AbstractMessage.java and AbstractMessageLite.java. If javac is + // invoked on both simultaneously, it works. (Or maybe the important + // point is whether or not DynamicMessage.java is compiled together with + // AbstractMessageLite.java -- not sure.) I suspect this is a compiler + // bug. + + @Override + public BuilderType mergeFrom(final ByteString data) + throws InvalidProtocolBufferException { + return super.mergeFrom(data); + } + + @Override + public BuilderType mergeFrom( + final ByteString data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return super.mergeFrom(data, extensionRegistry); + } + + @Override + public BuilderType mergeFrom(final byte[] data) + throws InvalidProtocolBufferException { + return super.mergeFrom(data); + } + + @Override + public BuilderType mergeFrom( + final byte[] data, final int off, final int len) + throws InvalidProtocolBufferException { + return super.mergeFrom(data, off, len); + } + + @Override + public BuilderType mergeFrom( + final byte[] data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return super.mergeFrom(data, extensionRegistry); + } + + @Override + public BuilderType mergeFrom( + final byte[] data, final int off, final int len, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return super.mergeFrom(data, off, len, extensionRegistry); + } + + @Override + public BuilderType mergeFrom(final InputStream input) + throws IOException { + return super.mergeFrom(input); + } + + @Override + public BuilderType mergeFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + return super.mergeFrom(input, extensionRegistry); + } + + @Override + public boolean mergeDelimitedFrom(final InputStream input) + throws IOException { + return super.mergeDelimitedFrom(input); + } + + @Override + public boolean mergeDelimitedFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + return super.mergeDelimitedFrom(input, extensionRegistry); + } + + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/AbstractMessageLite.java b/OsmAnd-java/src/com/google/protobuf/AbstractMessageLite.java new file mode 100644 index 0000000000..f0abb68849 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/AbstractMessageLite.java @@ -0,0 +1,342 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; + +/** + * A partial implementation of the {@link MessageLite} interface which + * implements as many methods of that interface as possible in terms of other + * methods. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class AbstractMessageLite implements MessageLite { + @Override +public ByteString toByteString() { + try { + final ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize()); + writeTo(out.getCodedOutput()); + return out.build(); + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + @Override +public byte[] toByteArray() { + try { + final byte[] result = new byte[getSerializedSize()]; + final CodedOutputStream output = CodedOutputStream.newInstance(result); + writeTo(output); + output.checkNoSpaceLeft(); + return result; + } catch (IOException e) { + throw new RuntimeException( + "Serializing to a byte array threw an IOException " + + "(should never happen).", e); + } + } + + @Override +public void writeTo(final OutputStream output) throws IOException { + final int bufferSize = + CodedOutputStream.computePreferredBufferSize(getSerializedSize()); + final CodedOutputStream codedOutput = + CodedOutputStream.newInstance(output, bufferSize); + writeTo(codedOutput); + codedOutput.flush(); + } + + @Override +public void writeDelimitedTo(final OutputStream output) throws IOException { + final int serialized = getSerializedSize(); + final int bufferSize = CodedOutputStream.computePreferredBufferSize( + CodedOutputStream.computeRawVarint32Size(serialized) + serialized); + final CodedOutputStream codedOutput = + CodedOutputStream.newInstance(output, bufferSize); + codedOutput.writeRawVarint32(serialized); + writeTo(codedOutput); + codedOutput.flush(); + } + + /** + * A partial implementation of the {@link Message.Builder} interface which + * implements as many methods of that interface as possible in terms of + * other methods. + */ + @SuppressWarnings("unchecked") + public static abstract class Builder + implements MessageLite.Builder { + // The compiler produces an error if this is not declared explicitly. + @Override + public abstract BuilderType clone(); + + @Override + public BuilderType mergeFrom(final CodedInputStream input) + throws IOException { + return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry()); + } + + // Re-defined here for return type covariance. + @Override + public abstract BuilderType mergeFrom( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException; + + @Override + public BuilderType mergeFrom(final ByteString data) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom( + final ByteString data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input, extensionRegistry); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom(final byte[] data) + throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length); + } + + @Override + public BuilderType mergeFrom(final byte[] data, final int off, + final int len) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom( + final byte[] data, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length, extensionRegistry); + } + + @Override + public BuilderType mergeFrom( + final byte[] data, final int off, final int len, + final ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input, extensionRegistry); + input.checkLastTagWas(0); + return (BuilderType) this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public BuilderType mergeFrom(final InputStream input) throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput); + codedInput.checkLastTagWas(0); + return (BuilderType) this; + } + + @Override + public BuilderType mergeFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput, extensionRegistry); + codedInput.checkLastTagWas(0); + return (BuilderType) this; + } + + /** + * An InputStream implementations which reads from some other InputStream + * but is limited to a particular number of bytes. Used by + * mergeDelimitedFrom(). This is intentionally package-private so that + * UnknownFieldSet can share it. + */ + static final class LimitedInputStream extends FilterInputStream { + private int limit; + + LimitedInputStream(InputStream in, int limit) { + super(in); + this.limit = limit; + } + + @Override + public int available() throws IOException { + return Math.min(super.available(), limit); + } + + @Override + public int read() throws IOException { + if (limit <= 0) { + return -1; + } + final int result = super.read(); + if (result >= 0) { + --limit; + } + return result; + } + + @Override + public int read(final byte[] b, final int off, int len) + throws IOException { + if (limit <= 0) { + return -1; + } + len = Math.min(len, limit); + final int result = super.read(b, off, len); + if (result >= 0) { + limit -= result; + } + return result; + } + + @Override + public long skip(final long n) throws IOException { + final long result = super.skip(Math.min(n, limit)); + if (result >= 0) { + limit -= result; + } + return result; + } + } + + @Override + public boolean mergeDelimitedFrom( + final InputStream input, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final int firstByte = input.read(); + if (firstByte == -1) { + return false; + } + final int size = CodedInputStream.readRawVarint32(firstByte, input); + final InputStream limitedInput = new LimitedInputStream(input, size); + mergeFrom(limitedInput, extensionRegistry); + return true; + } + + @Override + public boolean mergeDelimitedFrom(final InputStream input) + throws IOException { + return mergeDelimitedFrom(input, + ExtensionRegistryLite.getEmptyRegistry()); + } + + /** + * Construct an UninitializedMessageException reporting missing fields in + * the given message. + */ + protected static UninitializedMessageException + newUninitializedMessageException(MessageLite message) { + return new UninitializedMessageException(message); + } + + /** + * Adds the {@code values} to the {@code list}. This is a helper method + * used by generated code. Users should ignore it. + * + * @throws NullPointerException if any of the elements of {@code values} is + * null. + */ + protected static void addAll(final Iterable values, + final Collection list) { + for (final T value : values) { + if (value == null) { + throw new NullPointerException(); + } + } + if (values instanceof Collection) { + final + Collection collection = (Collection) values; + list.addAll(collection); + } else { + for (final T value : values) { + list.add(value); + } + } + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/BlockingRpcChannel.java b/OsmAnd-java/src/com/google/protobuf/BlockingRpcChannel.java new file mode 100644 index 0000000000..1e81143aea --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/BlockingRpcChannel.java @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + *

Abstract interface for a blocking RPC channel. {@code BlockingRpcChannel} + * is the blocking equivalent to {@link RpcChannel}. + * + * @author kenton@google.com Kenton Varda + * @author cpovirk@google.com Chris Povirk + */ +public interface BlockingRpcChannel { + /** + * Call the given method of the remote service and blocks until it returns. + * {@code callBlockingMethod()} is the blocking equivalent to + * {@link RpcChannel#callMethod}. + */ + Message callBlockingMethod( + Descriptors.MethodDescriptor method, + RpcController controller, + Message request, + Message responsePrototype) throws ServiceException; +} diff --git a/OsmAnd-java/src/com/google/protobuf/BlockingService.java b/OsmAnd-java/src/com/google/protobuf/BlockingService.java new file mode 100644 index 0000000000..ecc80096f5 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/BlockingService.java @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * Blocking equivalent to {@link Service}. + * + * @author kenton@google.com Kenton Varda + * @author cpovirk@google.com Chris Povirk + */ +public interface BlockingService { + /** + * Equivalent to {@link Service#getDescriptorForType}. + */ + Descriptors.ServiceDescriptor getDescriptorForType(); + + /** + * Equivalent to {@link Service#callMethod}, except that + * {@code callBlockingMethod()} returns the result of the RPC or throws a + * {@link ServiceException} if there is a failure, rather than passing the + * information to a callback. + */ + Message callBlockingMethod(Descriptors.MethodDescriptor method, + RpcController controller, + Message request) throws ServiceException; + + /** + * Equivalent to {@link Service#getRequestPrototype}. + */ + Message getRequestPrototype(Descriptors.MethodDescriptor method); + + /** + * Equivalent to {@link Service#getResponsePrototype}. + */ + Message getResponsePrototype(Descriptors.MethodDescriptor method); +} diff --git a/OsmAnd-java/src/com/google/protobuf/ByteString.java b/OsmAnd-java/src/com/google/protobuf/ByteString.java new file mode 100644 index 0000000000..2eabc71aa8 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/ByteString.java @@ -0,0 +1,391 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.List; + +/** + * Immutable array of bytes. + * + * @author crazybob@google.com Bob Lee + * @author kenton@google.com Kenton Varda + */ +public final class ByteString { + private final byte[] bytes; + + private ByteString(final byte[] bytes) { + this.bytes = bytes; + } + + /** + * Gets the byte at the given index. + * + * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size + */ + public byte byteAt(final int index) { + return bytes[index]; + } + + /** + * Gets the number of bytes. + */ + public int size() { + return bytes.length; + } + + /** + * Returns {@code true} if the size is {@code 0}, {@code false} otherwise. + */ + public boolean isEmpty() { + return bytes.length == 0; + } + + // ================================================================= + // byte[] -> ByteString + + /** + * Empty ByteString. + */ + public static final ByteString EMPTY = new ByteString(new byte[0]); + + /** + * Copies the given bytes into a {@code ByteString}. + */ + public static ByteString copyFrom(final byte[] bytes, final int offset, + final int size) { + final byte[] copy = new byte[size]; + System.arraycopy(bytes, offset, copy, 0, size); + return new ByteString(copy); + } + + /** + * Copies the given bytes into a {@code ByteString}. + */ + public static ByteString copyFrom(final byte[] bytes) { + return copyFrom(bytes, 0, bytes.length); + } + + /** + * Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into + * a {@code ByteString}. + */ + public static ByteString copyFrom(final ByteBuffer bytes, final int size) { + final byte[] copy = new byte[size]; + bytes.get(copy); + return new ByteString(copy); + } + + /** + * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into + * a {@code ByteString}. + */ + public static ByteString copyFrom(final ByteBuffer bytes) { + return copyFrom(bytes, bytes.remaining()); + } + + /** + * Encodes {@code text} into a sequence of bytes using the named charset + * and returns the result as a {@code ByteString}. + */ + public static ByteString copyFrom(final String text, final String charsetName) + throws UnsupportedEncodingException { + return new ByteString(text.getBytes(charsetName)); + } + + /** + * Encodes {@code text} into a sequence of UTF-8 bytes and returns the + * result as a {@code ByteString}. + */ + public static ByteString copyFromUtf8(final String text) { + try { + return new ByteString(text.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 not supported?", e); + } + } + + /** + * Concatenates all byte strings in the list and returns the result. + * + *

The returned {@code ByteString} is not necessarily a unique object. + * If the list is empty, the returned object is the singleton empty + * {@code ByteString}. If the list has only one element, that + * {@code ByteString} will be returned without copying. + */ + public static ByteString copyFrom(List list) { + if (list.size() == 0) { + return EMPTY; + } else if (list.size() == 1) { + return list.get(0); + } + + int size = 0; + for (ByteString str : list) { + size += str.size(); + } + byte[] bytes = new byte[size]; + int pos = 0; + for (ByteString str : list) { + System.arraycopy(str.bytes, 0, bytes, pos, str.size()); + pos += str.size(); + } + return new ByteString(bytes); + } + + // ================================================================= + // ByteString -> byte[] + + /** + * Copies bytes into a buffer at the given offset. + * + * @param target buffer to copy into + * @param offset in the target buffer + */ + public void copyTo(final byte[] target, final int offset) { + System.arraycopy(bytes, 0, target, offset, bytes.length); + } + + /** + * Copies bytes into a buffer. + * + * @param target buffer to copy into + * @param sourceOffset offset within these bytes + * @param targetOffset offset within the target buffer + * @param size number of bytes to copy + */ + public void copyTo(final byte[] target, final int sourceOffset, + final int targetOffset, + final int size) { + System.arraycopy(bytes, sourceOffset, target, targetOffset, size); + } + + /** + * Copies bytes to a {@code byte[]}. + */ + public byte[] toByteArray() { + final int size = bytes.length; + final byte[] copy = new byte[size]; + System.arraycopy(bytes, 0, copy, 0, size); + return copy; + } + + /** + * Constructs a new read-only {@code java.nio.ByteBuffer} with the + * same backing byte array. + */ + public ByteBuffer asReadOnlyByteBuffer() { + final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + return byteBuffer.asReadOnlyBuffer(); + } + + /** + * Constructs a new {@code String} by decoding the bytes using the + * specified charset. + */ + public String toString(final String charsetName) + throws UnsupportedEncodingException { + return new String(bytes, charsetName); + } + + /** + * Constructs a new {@code String} by decoding the bytes as UTF-8. + */ + public String toStringUtf8() { + try { + return new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 not supported?", e); + } + } + + // ================================================================= + // equals() and hashCode() + + @Override + public boolean equals(final Object o) { + if (o == this) { + return true; + } + + if (!(o instanceof ByteString)) { + return false; + } + + final ByteString other = (ByteString) o; + final int size = bytes.length; + if (size != other.bytes.length) { + return false; + } + + final byte[] thisBytes = bytes; + final byte[] otherBytes = other.bytes; + for (int i = 0; i < size; i++) { + if (thisBytes[i] != otherBytes[i]) { + return false; + } + } + + return true; + } + + private volatile int hash = 0; + + @Override + public int hashCode() { + int h = hash; + + if (h == 0) { + final byte[] thisBytes = bytes; + final int size = bytes.length; + + h = size; + for (int i = 0; i < size; i++) { + h = h * 31 + thisBytes[i]; + } + if (h == 0) { + h = 1; + } + + hash = h; + } + + return h; + } + + // ================================================================= + // Input stream + + /** + * Creates an {@code InputStream} which can be used to read the bytes. + */ + public InputStream newInput() { + return new ByteArrayInputStream(bytes); + } + + /** + * Creates a {@link CodedInputStream} which can be used to read the bytes. + * Using this is more efficient than creating a {@link CodedInputStream} + * wrapping the result of {@link #newInput()}. + */ + public CodedInputStream newCodedInput() { + // We trust CodedInputStream not to modify the bytes, or to give anyone + // else access to them. + return CodedInputStream.newInstance(bytes); + } + + // ================================================================= + // Output stream + + /** + * Creates a new {@link Output} with the given initial capacity. + */ + public static Output newOutput(final int initialCapacity) { + return new Output(new ByteArrayOutputStream(initialCapacity)); + } + + /** + * Creates a new {@link Output}. + */ + public static Output newOutput() { + return newOutput(32); + } + + /** + * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to + * create the {@code ByteString} instance. + */ + public static final class Output extends FilterOutputStream { + private final ByteArrayOutputStream bout; + + /** + * Constructs a new output with the given initial capacity. + */ + private Output(final ByteArrayOutputStream bout) { + super(bout); + this.bout = bout; + } + + /** + * Creates a {@code ByteString} instance from this {@code Output}. + */ + public ByteString toByteString() { + final byte[] byteArray = bout.toByteArray(); + return new ByteString(byteArray); + } + } + + /** + * Constructs a new ByteString builder, which allows you to efficiently + * construct a {@code ByteString} by writing to a {@link CodedOutputStream}. + * Using this is much more efficient than calling {@code newOutput()} and + * wrapping that in a {@code CodedOutputStream}. + * + *

This is package-private because it's a somewhat confusing interface. + * Users can call {@link Message#toByteString()} instead of calling this + * directly. + * + * @param size The target byte size of the {@code ByteString}. You must + * write exactly this many bytes before building the result. + */ + static CodedBuilder newCodedBuilder(final int size) { + return new CodedBuilder(size); + } + + /** See {@link ByteString#newCodedBuilder(int)}. */ + static final class CodedBuilder { + private final CodedOutputStream output; + private final byte[] buffer; + + private CodedBuilder(final int size) { + buffer = new byte[size]; + output = CodedOutputStream.newInstance(buffer); + } + + public ByteString build() { + output.checkNoSpaceLeft(); + + // We can be confident that the CodedOutputStream will not modify the + // underlying bytes anymore because it already wrote all of them. So, + // no need to make a copy. + return new ByteString(buffer); + } + + public CodedOutputStream getCodedOutput() { + return output; + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java b/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java new file mode 100644 index 0000000000..45004e2e28 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java @@ -0,0 +1,924 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; + +/** + * Reads and decodes protocol message fields. + * + * This class contains two kinds of methods: methods that read specific + * protocol message constructs and field types (e.g. {@link #readTag()} and + * {@link #readInt32()}) and methods that read low-level values (e.g. + * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading + * encoded protocol messages, you should use the former methods, but if you are + * reading some other format of your own design, use the latter. + * + * @author kenton@google.com Kenton Varda + */ +public final class CodedInputStream { + /** + * Create a new CodedInputStream wrapping the given InputStream. + */ + public static CodedInputStream newInstance(final InputStream input) { + return new CodedInputStream(input); + } + + /** + * Create a new CodedInputStream wrapping the given byte array. + */ + public static CodedInputStream newInstance(final byte[] buf) { + return newInstance(buf, 0, buf.length); + } + + /** + * Create a new CodedInputStream wrapping the given byte array slice. + */ + public static CodedInputStream newInstance(final byte[] buf, final int off, + final int len) { + return new CodedInputStream(buf, off, len); + } + + // ----------------------------------------------------------------- + // begin osmand change + public static CodedInputStream newInstance(RandomAccessFile raf) { + return new CodedInputStream(raf); + } + // end osmand change + + + /** + * Attempt to read a field tag, returning zero if we have reached EOF. + * Protocol message parsers use this to read tags, since a protocol message + * may legally end wherever a tag occurs, and zero is not a valid tag number. + */ + public int readTag() throws IOException { + if (isAtEnd()) { + lastTag = 0; + return 0; + } + + lastTag = readRawVarint32(); + if (WireFormat.getTagFieldNumber(lastTag) == 0) { + // If we actually read zero (or any tag number corresponding to field + // number zero), that's not a valid tag. + throw InvalidProtocolBufferException.invalidTag(); + } + return lastTag; + } + + /** + * Verifies that the last call to readTag() returned the given tag value. + * This is used to verify that a nested group ended with the correct + * end tag. + * + * @throws InvalidProtocolBufferException {@code value} does not match the + * last tag. + */ + public void checkLastTagWas(final int value) + throws InvalidProtocolBufferException { + if (lastTag != value) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + } + + /** + * Reads and discards a single field, given its tag value. + * + * @return {@code false} if the tag is an endgroup tag, in which case + * nothing is skipped. Otherwise, returns {@code true}. + */ + public boolean skipField(final int tag) throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + readInt32(); + return true; + case WireFormat.WIRETYPE_FIXED64: + readRawLittleEndian64(); + return true; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + skipRawBytes(readRawVarint32()); + return true; + case WireFormat.WIRETYPE_START_GROUP: + skipMessage(); + checkLastTagWas( + WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), + WireFormat.WIRETYPE_END_GROUP)); + return true; + case WireFormat.WIRETYPE_END_GROUP: + return false; + case WireFormat.WIRETYPE_FIXED32: + readRawLittleEndian32(); + return true; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + /** + * Reads and discards an entire message. This will read either until EOF + * or until an endgroup tag, whichever comes first. + */ + public void skipMessage() throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0 || !skipField(tag)) { + return; + } + } + } + + // ----------------------------------------------------------------- + + /** Read a {@code double} field value from the stream. */ + public double readDouble() throws IOException { + return Double.longBitsToDouble(readRawLittleEndian64()); + } + + /** Read a {@code float} field value from the stream. */ + public float readFloat() throws IOException { + return Float.intBitsToFloat(readRawLittleEndian32()); + } + + /** Read a {@code uint64} field value from the stream. */ + public long readUInt64() throws IOException { + return readRawVarint64(); + } + + /** Read an {@code int64} field value from the stream. */ + public long readInt64() throws IOException { + return readRawVarint64(); + } + + /** Read an {@code int32} field value from the stream. */ + public int readInt32() throws IOException { + return readRawVarint32(); + } + + /** Read a {@code fixed64} field value from the stream. */ + public long readFixed64() throws IOException { + return readRawLittleEndian64(); + } + + /** Read a {@code fixed32} field value from the stream. */ + public int readFixed32() throws IOException { + return readRawLittleEndian32(); + } + + /** Read a {@code bool} field value from the stream. */ + public boolean readBool() throws IOException { + return readRawVarint32() != 0; + } + + /** Read a {@code string} field value from the stream. */ + public String readString() throws IOException { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + final String result = new String(buffer, bufferPos, size, "UTF-8"); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return new String(readRawBytes(size), "UTF-8"); + } + } + + /** Read a {@code group} field value from the stream. */ + public void readGroup(final int fieldNumber, + final MessageLite.Builder builder, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + ++recursionDepth; + builder.mergeFrom(this, extensionRegistry); + checkLastTagWas( + WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); + --recursionDepth; + } + + /** + * Reads a {@code group} field value from the stream and merges it into the + * given {@link UnknownFieldSet}. + * + * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so + * you can just call {@link #readGroup}. + */ + @Deprecated + public void readUnknownGroup(final int fieldNumber, + final MessageLite.Builder builder) + throws IOException { + // We know that UnknownFieldSet will ignore any ExtensionRegistry so it + // is safe to pass null here. (We can't call + // ExtensionRegistry.getEmptyRegistry() because that would make this + // class depend on ExtensionRegistry, which is not part of the lite + // library.) + readGroup(fieldNumber, builder, null); + } + + /** Read an embedded message field value from the stream. */ + public void readMessage(final MessageLite.Builder builder, + final ExtensionRegistryLite extensionRegistry) + throws IOException { + final int length = readRawVarint32(); + if (recursionDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + final int oldLimit = pushLimit(length); + ++recursionDepth; + builder.mergeFrom(this, extensionRegistry); + checkLastTagWas(0); + --recursionDepth; + popLimit(oldLimit); + } + + /** Read a {@code bytes} field value from the stream. */ + public ByteString readBytes() throws IOException { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + final ByteString result = ByteString.copyFrom(buffer, bufferPos, size); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return ByteString.copyFrom(readRawBytes(size)); + } + } + + /** Read a {@code uint32} field value from the stream. */ + public int readUInt32() throws IOException { + return readRawVarint32(); + } + + /** + * Read an enum field value from the stream. Caller is responsible + * for converting the numeric value to an actual enum. + */ + public int readEnum() throws IOException { + return readRawVarint32(); + } + + /** Read an {@code sfixed32} field value from the stream. */ + public int readSFixed32() throws IOException { + return readRawLittleEndian32(); + } + + /** Read an {@code sfixed64} field value from the stream. */ + public long readSFixed64() throws IOException { + return readRawLittleEndian64(); + } + + /** Read an {@code sint32} field value from the stream. */ + public int readSInt32() throws IOException { + return decodeZigZag32(readRawVarint32()); + } + + /** Read an {@code sint64} field value from the stream. */ + public long readSInt64() throws IOException { + return decodeZigZag64(readRawVarint64()); + } + + // ================================================================= + + /** + * Read a raw Varint from the stream. If larger than 32 bits, discard the + * upper bits. + */ + public int readRawVarint32() throws IOException { + byte tmp = readRawByte(); + if (tmp >= 0) { + return tmp; + } + int result = tmp & 0x7f; + if ((tmp = readRawByte()) >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = readRawByte()) >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = readRawByte()) >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = readRawByte()) << 28; + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) { + if (readRawByte() >= 0) { + return result; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + } + } + } + return result; + } + + /** + * Reads a varint from the input one byte at a time, so that it does not + * read any bytes after the end of the varint. If you simply wrapped the + * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)} + * then you would probably end up reading past the end of the varint since + * CodedInputStream buffers its input. + */ + static int readRawVarint32(final InputStream input) throws IOException { + final int firstByte = input.read(); + if (firstByte == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return readRawVarint32(firstByte, input); + } + + /** + * Like {@link #readRawVarint32(InputStream)}, but expects that the caller + * has already read one byte. This allows the caller to determine if EOF + * has been reached before attempting to read. + */ + static int readRawVarint32(final int firstByte, + final InputStream input) throws IOException { + if ((firstByte & 0x80) == 0) { + return firstByte; + } + + int result = firstByte & 0x7f; + int offset = 7; + for (; offset < 32; offset += 7) { + final int b = input.read(); + if (b == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + result |= (b & 0x7f) << offset; + if ((b & 0x80) == 0) { + return result; + } + } + // Keep reading up to 64 bits. + for (; offset < 64; offset += 7) { + final int b = input.read(); + if (b == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + if ((b & 0x80) == 0) { + return result; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + /** Read a raw Varint from the stream. */ + public long readRawVarint64() throws IOException { + int shift = 0; + long result = 0; + while (shift < 64) { + final byte b = readRawByte(); + result |= (long)(b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + /** Read a 32-bit little-endian integer from the stream. */ + public int readRawLittleEndian32() throws IOException { + final byte b1 = readRawByte(); + final byte b2 = readRawByte(); + final byte b3 = readRawByte(); + final byte b4 = readRawByte(); + return (((int)b1 & 0xff) ) | + (((int)b2 & 0xff) << 8) | + (((int)b3 & 0xff) << 16) | + (((int)b4 & 0xff) << 24); + } + + /** Read a 64-bit little-endian integer from the stream. */ + public long readRawLittleEndian64() throws IOException { + final byte b1 = readRawByte(); + final byte b2 = readRawByte(); + final byte b3 = readRawByte(); + final byte b4 = readRawByte(); + final byte b5 = readRawByte(); + final byte b6 = readRawByte(); + final byte b7 = readRawByte(); + final byte b8 = readRawByte(); + return (((long)b1 & 0xff) ) | + (((long)b2 & 0xff) << 8) | + (((long)b3 & 0xff) << 16) | + (((long)b4 & 0xff) << 24) | + (((long)b5 & 0xff) << 32) | + (((long)b6 & 0xff) << 40) | + (((long)b7 & 0xff) << 48) | + (((long)b8 & 0xff) << 56); + } + + /** + * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers + * into values that can be efficiently encoded with varint. (Otherwise, + * negative values must be sign-extended to 64 bits to be varint encoded, + * thus always taking 10 bytes on the wire.) + * + * @param n An unsigned 32-bit integer, stored in a signed int because + * Java has no explicit unsigned support. + * @return A signed 32-bit integer. + */ + public static int decodeZigZag32(final int n) { + return (n >>> 1) ^ -(n & 1); + } + + /** + * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers + * into values that can be efficiently encoded with varint. (Otherwise, + * negative values must be sign-extended to 64 bits to be varint encoded, + * thus always taking 10 bytes on the wire.) + * + * @param n An unsigned 64-bit integer, stored in a signed int because + * Java has no explicit unsigned support. + * @return A signed 64-bit integer. + */ + public static long decodeZigZag64(final long n) { + return (n >>> 1) ^ -(n & 1); + } + + // ----------------------------------------------------------------- + + private final byte[] buffer; + private RandomAccessFile raf; + private int bufferSize; + private int bufferSizeAfterLimit; + private int bufferPos; + private final InputStream input; + private int lastTag; + + /** + * The total number of bytes read before the current buffer. The total + * bytes read up to the current position can be computed as + * {@code totalBytesRetired + bufferPos}. This value may be negative if + * reading started in the middle of the current buffer (e.g. if the + * constructor that takes a byte array and an offset was used). + */ + private int totalBytesRetired; + + /** The absolute position of the end of the current message. */ + private int currentLimit = Integer.MAX_VALUE; + + /** See setRecursionLimit() */ + private int recursionDepth; + private int recursionLimit = DEFAULT_RECURSION_LIMIT; + + /** See setSizeLimit() */ + private int sizeLimit = DEFAULT_SIZE_LIMIT; + + private static final int DEFAULT_RECURSION_LIMIT = 64; + private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB + private static final int BUFFER_SIZE = 5 * 1024; + + + private CodedInputStream(final byte[] buffer, final int off, final int len) { + this.buffer = buffer; + bufferSize = off + len; + bufferPos = off; + totalBytesRetired = -off; + input = null; + } + + private CodedInputStream(final InputStream input) { + buffer = new byte[BUFFER_SIZE]; + bufferSize = 0; + bufferPos = 0; + totalBytesRetired = 0; + this.input = input; + } + + private CodedInputStream(final RandomAccessFile raf) { + buffer = new byte[BUFFER_SIZE]; + this.bufferSize = 0; + bufferPos = 0; + totalBytesRetired = 0; + this.raf = raf; + input = null; + } + + /** + * Set the maximum message recursion depth. In order to prevent malicious + * messages from causing stack overflows, {@code CodedInputStream} limits + * how deeply messages may be nested. The default limit is 64. + * + * @return the old limit. + */ + public int setRecursionLimit(final int limit) { + if (limit < 0) { + throw new IllegalArgumentException( + "Recursion limit cannot be negative: " + limit); + } + final int oldLimit = recursionLimit; + recursionLimit = limit; + return oldLimit; + } + + /** + * Set the maximum message size. In order to prevent malicious + * messages from exhausting memory or causing integer overflows, + * {@code CodedInputStream} limits how large a message may be. + * The default limit is 64MB. You should set this limit as small + * as you can without harming your app's functionality. Note that + * size limits only apply when reading from an {@code InputStream}, not + * when constructed around a raw byte array (nor with + * {@link ByteString#newCodedInput}). + *

+ * If you want to read several messages from a single CodedInputStream, you + * could call {@link #resetSizeCounter()} after each one to avoid hitting the + * size limit. + * + * @return the old limit. + */ + public int setSizeLimit(final int limit) { + if (limit < 0) { + throw new IllegalArgumentException( + "Size limit cannot be negative: " + limit); + } + final int oldLimit = sizeLimit; + sizeLimit = limit; + return oldLimit; + } + + /** + * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). + */ + public void resetSizeCounter() { + totalBytesRetired = -bufferPos; + } + + /** + * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This + * is called when descending into a length-delimited embedded message. + * + *

Note that {@code pushLimit()} does NOT affect how many bytes the + * {@code CodedInputStream} reads from an underlying {@code InputStream} when + * refreshing its buffer. If you need to prevent reading past a certain + * point in the underlying {@code InputStream} (e.g. because you expect it to + * contain more data after the end of the message which you need to handle + * differently) then you must place a wrapper around you {@code InputStream} + * which limits the amount of data that can be read from it. + * + * @return the old limit. + */ + public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { + if (byteLimit < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + byteLimit += totalBytesRetired + bufferPos; + final int oldLimit = currentLimit; + if (byteLimit > oldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + currentLimit = byteLimit; + + recomputeBufferSizeAfterLimit(); + + return oldLimit; + } + + private void recomputeBufferSizeAfterLimit() { + bufferSize += bufferSizeAfterLimit; + final int bufferEnd = totalBytesRetired + bufferSize; + if (bufferEnd > currentLimit) { + // Limit is in current buffer. + bufferSizeAfterLimit = bufferEnd - currentLimit; + bufferSize -= bufferSizeAfterLimit; + } else { + bufferSizeAfterLimit = 0; + } + } + + /** + * Discards the current limit, returning to the previous limit. + * + * @param oldLimit The old limit, as returned by {@code pushLimit}. + */ + public void popLimit(final int oldLimit) { + currentLimit = oldLimit; + recomputeBufferSizeAfterLimit(); + } + + /** + * Returns the number of bytes to be read before the current limit. + * If no limit is set, returns -1. + */ + public int getBytesUntilLimit() { + if (currentLimit == Integer.MAX_VALUE) { + return -1; + } + + final int currentAbsolutePosition = totalBytesRetired + bufferPos; + return currentLimit - currentAbsolutePosition; + } + + /** + * Returns true if the stream has reached the end of the input. This is the + * case if either the end of the underlying input source has been reached or + * if the stream has reached a limit created using {@link #pushLimit(int)}. + */ + public boolean isAtEnd() throws IOException { + return bufferPos == bufferSize && !refillBuffer(false); + } + + /** + * The total bytes read up to the current position. Calling + * {@link #resetSizeCounter()} resets this value to zero. + */ + public int getTotalBytesRead() { + return totalBytesRetired + bufferPos; + } + + /** + * Called with {@code this.buffer} is empty to read more bytes from the + * input. If {@code mustSucceed} is true, refillBuffer() gurantees that + * either there will be at least one byte in the buffer when it returns + * or it will throw an exception. If {@code mustSucceed} is false, + * refillBuffer() returns false if no more bytes were available. + */ + private boolean refillBuffer(final boolean mustSucceed) throws IOException { + if (bufferPos < bufferSize) { + throw new IllegalStateException( + "refillBuffer() called when buffer wasn't empty."); + } + + if (totalBytesRetired + bufferSize == currentLimit) { + // Oops, we hit a limit. + if (mustSucceed) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else { + return false; + } + } + + totalBytesRetired += bufferSize; + + bufferPos = 0; + if (raf != null) { + // osmand change + long remain = raf.length() - raf.getFilePointer(); + bufferSize = (int) Math.min(remain, buffer.length); + if(bufferSize > 0) { + raf.readFully(buffer, 0, bufferSize); + } else { + bufferSize = -1; + } + } else { + bufferSize = (input == null) ? -1 : input.read(buffer); + } + if (bufferSize == 0 || bufferSize < -1) { + throw new IllegalStateException( + "InputStream#read(byte[]) returned invalid result: " + bufferSize + + "\nThe InputStream implementation is buggy."); + } + if (bufferSize == -1) { + bufferSize = 0; + if (mustSucceed) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else { + return false; + } + } else { + recomputeBufferSizeAfterLimit(); + final int totalBytesRead = + totalBytesRetired + bufferSize + bufferSizeAfterLimit; + if (totalBytesRead > sizeLimit || totalBytesRead < 0) { + throw InvalidProtocolBufferException.sizeLimitExceeded(); + } + return true; + } + } + + /** + * Read one byte from the input. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + public byte readRawByte() throws IOException { + if (bufferPos == bufferSize) { + refillBuffer(true); + } + return buffer[bufferPos++]; + } + + /** + * Read a fixed size of bytes from the input. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + public byte[] readRawBytes(final int size) throws IOException { + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + + if (totalBytesRetired + bufferPos + size > currentLimit) { + // Read to the end of the stream anyway. + skipRawBytes(currentLimit - totalBytesRetired - bufferPos); + // Then fail. + throw InvalidProtocolBufferException.truncatedMessage(); + } + + if (size <= bufferSize - bufferPos) { + // We have all the bytes we need already. + final byte[] bytes = new byte[size]; + System.arraycopy(buffer, bufferPos, bytes, 0, size); + bufferPos += size; + return bytes; + } else if (size < BUFFER_SIZE) { + // Reading more bytes than are in the buffer, but not an excessive number + // of bytes. We can safely allocate the resulting array ahead of time. + + // First copy what we have. + final byte[] bytes = new byte[size]; + int pos = bufferSize - bufferPos; + System.arraycopy(buffer, bufferPos, bytes, 0, pos); + bufferPos = bufferSize; + + // We want to use refillBuffer() and then copy from the buffer into our + // byte array rather than reading directly into our byte array because + // the input may be unbuffered. + refillBuffer(true); + + while (size - pos > bufferSize) { + System.arraycopy(buffer, 0, bytes, pos, bufferSize); + pos += bufferSize; + bufferPos = bufferSize; + refillBuffer(true); + } + + System.arraycopy(buffer, 0, bytes, pos, size - pos); + bufferPos = size - pos; + + return bytes; + } else { + // The size is very large. For security reasons, we can't allocate the + // entire byte array yet. The size comes directly from the input, so a + // maliciously-crafted message could provide a bogus very large size in + // order to trick the app into allocating a lot of memory. We avoid this + // by allocating and reading only a small chunk at a time, so that the + // malicious message must actually *be* extremely large to cause + // problems. Meanwhile, we limit the allowed size of a message elsewhere. + + // Remember the buffer markers since we'll have to copy the bytes out of + // it later. + final int originalBufferPos = bufferPos; + final int originalBufferSize = bufferSize; + + // Mark the current buffer consumed. + totalBytesRetired += bufferSize; + bufferPos = 0; + bufferSize = 0; + + // Read all the rest of the bytes we need. + int sizeLeft = size - (originalBufferSize - originalBufferPos); + final List chunks = new ArrayList(); + + while (sizeLeft > 0) { + final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; + int pos = 0; + while (pos < chunk.length) { + + final int n; + // osmand change + if(raf != null) { + raf.readFully(chunk, pos, chunk.length - pos); + n = chunk.length - pos; + } else { + n = (input == null) ? -1 : + input.read(chunk, pos, chunk.length - pos); + } + if (n == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + totalBytesRetired += n; + pos += n; + } + sizeLeft -= chunk.length; + chunks.add(chunk); + } + + // OK, got everything. Now concatenate it all into one buffer. + final byte[] bytes = new byte[size]; + + // Start by copying the leftover bytes from this.buffer. + int pos = originalBufferSize - originalBufferPos; + System.arraycopy(buffer, originalBufferPos, bytes, 0, pos); + + // And now all the chunks. + for (final byte[] chunk : chunks) { + System.arraycopy(chunk, 0, bytes, pos, chunk.length); + pos += chunk.length; + } + // Done. + return bytes; + } + } + + /** + * Reads and discards {@code size} bytes. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + public void skipRawBytes(final int size) throws IOException { + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + + if (totalBytesRetired + bufferPos + size > currentLimit) { + // Read to the end of the stream anyway. + skipRawBytes(currentLimit - totalBytesRetired - bufferPos); + // Then fail. + throw InvalidProtocolBufferException.truncatedMessage(); + } + + if (size <= bufferSize - bufferPos) { + // We have all the bytes we need already. + bufferPos += size; + } else { + // Skipping more bytes than are in the buffer. First skip what we have. + int pos = bufferSize - bufferPos; + totalBytesRetired += bufferSize; // ? pos incorrect + bufferPos = 0; + bufferSize = 0; + + // Then skip directly from the InputStream for the rest. + while (pos < size) { + // osmand change + final int n ; + if(raf != null) { + n = raf.skipBytes(size - pos); + } else { + n = (input == null) ? -1 : (int) input.skip(size - pos); + } + if (n <= 0) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + pos += n; + totalBytesRetired += n; + } + } + } + + // osmand change + public void seek(long pointer) throws IOException { + if (pointer - totalBytesRetired >= 0 && pointer - totalBytesRetired < bufferSize) { + if (pointer > currentLimit) { + // Then fail. + throw InvalidProtocolBufferException.truncatedMessage(); + } + bufferPos = (int) (pointer - totalBytesRetired); + } else { + totalBytesRetired = (int) pointer; + bufferSizeAfterLimit = 0; + raf.seek(pointer); + bufferPos = 0; + bufferSize = 0; + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java b/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java new file mode 100644 index 0000000000..02c1ee5d0f --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java @@ -0,0 +1,825 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; + +/** + * Reads and decodes protocol message fields. + * + * This class contains two kinds of methods: methods that read specific + * protocol message constructs and field types (e.g. {@link #readTag()} and + * {@link #readInt32()}) and methods that read low-level values (e.g. + * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading + * encoded protocol messages, you should use the former methods, but if you are + * reading some other format of your own design, use the latter. + * + * @author kenton@google.com Kenton Varda + * OSMAND change + */ +public final class CodedInputStreamRAF { + /** + * Create a new CodedInputStream wrapping the given InputStream. + */ + public static CodedInputStreamRAF newInstance(RandomAccessFile raf) { + return new CodedInputStreamRAF(raf, BUFFER_SIZE_DEF); + } + + public static CodedInputStreamRAF newInstance(RandomAccessFile raf, int bufferSize) { + return new CodedInputStreamRAF(raf, bufferSize); + } + + + // ----------------------------------------------------------------- + + /** + * Attempt to read a field tag, returning zero if we have reached EOF. + * Protocol message parsers use this to read tags, since a protocol message + * may legally end wherever a tag occurs, and zero is not a valid tag number. + */ + public int readTag() throws IOException { + if (isAtEnd()) { + lastTag = 0; + return 0; + } + + lastTag = readRawVarint32(); + if (WireFormat.getTagFieldNumber(lastTag) == 0) { + // If we actually read zero (or any tag number corresponding to field + // number zero), that's not a valid tag. + throw InvalidProtocolBufferException.invalidTag(); + } + return lastTag; + } + + /** + * Verifies that the last call to readTag() returned the given tag value. + * This is used to verify that a nested group ended with the correct + * end tag. + * + * @throws InvalidProtocolBufferException {@code value} does not match the + * last tag. + */ + public void checkLastTagWas(final int value) + throws InvalidProtocolBufferException { + if (lastTag != value) { + throw InvalidProtocolBufferException.invalidEndTag(); + } + } + + /** + * Reads and discards a single field, given its tag value. + * + * @return {@code false} if the tag is an endgroup tag, in which case + * nothing is skipped. Otherwise, returns {@code true}. + */ + public boolean skipField(final int tag) throws IOException { + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + readInt32(); + return true; + case WireFormat.WIRETYPE_FIXED64: + readRawLittleEndian64(); + return true; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + skipRawBytes(readRawVarint32()); + return true; + case WireFormat.WIRETYPE_START_GROUP: + skipMessage(); + checkLastTagWas( + WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), + WireFormat.WIRETYPE_END_GROUP)); + return true; + case WireFormat.WIRETYPE_END_GROUP: + return false; + case WireFormat.WIRETYPE_FIXED32: + readRawLittleEndian32(); + return true; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + /** + * Reads and discards an entire message. This will read either until EOF + * or until an endgroup tag, whichever comes first. + */ + public void skipMessage() throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0 || !skipField(tag)) { + return; + } + } + } + + // ----------------------------------------------------------------- + + /** Read a {@code double} field value from the stream. */ + public double readDouble() throws IOException { + return Double.longBitsToDouble(readRawLittleEndian64()); + } + + /** Read a {@code float} field value from the stream. */ + public float readFloat() throws IOException { + return Float.intBitsToFloat(readRawLittleEndian32()); + } + + /** Read a {@code uint64} field value from the stream. */ + public long readUInt64() throws IOException { + return readRawVarint64(); + } + + /** Read an {@code int64} field value from the stream. */ + public long readInt64() throws IOException { + return readRawVarint64(); + } + + /** Read an {@code int32} field value from the stream. */ + public int readInt32() throws IOException { + return readRawVarint32(); + } + + /** Read a {@code fixed64} field value from the stream. */ + public long readFixed64() throws IOException { + return readRawLittleEndian64(); + } + + /** Read a {@code fixed32} field value from the stream. */ + public int readFixed32() throws IOException { + return readRawLittleEndian32(); + } + + /** Read a {@code bool} field value from the stream. */ + public boolean readBool() throws IOException { + return readRawVarint32() != 0; + } + + /** Read a {@code string} field value from the stream. */ + public String readString() throws IOException { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + final String result = new String(buffer, bufferPos, size, "UTF-8"); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return new String(readRawBytes(size), "UTF-8"); + } + } + + + + + /** Read a {@code bytes} field value from the stream. */ + public ByteString readBytes() throws IOException { + final int size = readRawVarint32(); + if (size <= (bufferSize - bufferPos) && size > 0) { + // Fast path: We already have the bytes in a contiguous buffer, so + // just copy directly from it. + final ByteString result = ByteString.copyFrom(buffer, bufferPos, size); + bufferPos += size; + return result; + } else { + // Slow path: Build a byte array first then copy it. + return ByteString.copyFrom(readRawBytes(size)); + } + } + + /** Read a {@code uint32} field value from the stream. */ + public int readUInt32() throws IOException { + return readRawVarint32(); + } + + /** + * Read an enum field value from the stream. Caller is responsible + * for converting the numeric value to an actual enum. + */ + public int readEnum() throws IOException { + return readRawVarint32(); + } + + /** Read an {@code sfixed32} field value from the stream. */ + public int readSFixed32() throws IOException { + return readRawLittleEndian32(); + } + + /** Read an {@code sfixed64} field value from the stream. */ + public long readSFixed64() throws IOException { + return readRawLittleEndian64(); + } + + /** Read an {@code sint32} field value from the stream. */ + public int readSInt32() throws IOException { + return decodeZigZag32(readRawVarint32()); + } + + /** Read an {@code sint64} field value from the stream. */ + public long readSInt64() throws IOException { + return decodeZigZag64(readRawVarint64()); + } + + // ================================================================= + + /** + * Read a raw Varint from the stream. If larger than 32 bits, discard the + * upper bits. + */ + public int readRawVarint32() throws IOException { + byte tmp = readRawByte(); + if (tmp >= 0) { + return tmp; + } + int result = tmp & 0x7f; + if ((tmp = readRawByte()) >= 0) { + result |= tmp << 7; + } else { + result |= (tmp & 0x7f) << 7; + if ((tmp = readRawByte()) >= 0) { + result |= tmp << 14; + } else { + result |= (tmp & 0x7f) << 14; + if ((tmp = readRawByte()) >= 0) { + result |= tmp << 21; + } else { + result |= (tmp & 0x7f) << 21; + result |= (tmp = readRawByte()) << 28; + if (tmp < 0) { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) { + if (readRawByte() >= 0) { + return result; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + } + } + } + return result; + } + + /** + * Reads a varint from the input one byte at a time, so that it does not + * read any bytes after the end of the varint. If you simply wrapped the + * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)} + * then you would probably end up reading past the end of the varint since + * CodedInputStream buffers its input. + */ + static int readRawVarint32(final InputStream input) throws IOException { + final int firstByte = input.read(); + if (firstByte == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + return readRawVarint32(firstByte, input); + } + + /** + * Like {@link #readRawVarint32(InputStream)}, but expects that the caller + * has already read one byte. This allows the caller to determine if EOF + * has been reached before attempting to read. + */ + static int readRawVarint32(final int firstByte, + final InputStream input) throws IOException { + if ((firstByte & 0x80) == 0) { + return firstByte; + } + + int result = firstByte & 0x7f; + int offset = 7; + for (; offset < 32; offset += 7) { + final int b = input.read(); + if (b == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + result |= (b & 0x7f) << offset; + if ((b & 0x80) == 0) { + return result; + } + } + // Keep reading up to 64 bits. + for (; offset < 64; offset += 7) { + final int b = input.read(); + if (b == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + if ((b & 0x80) == 0) { + return result; + } + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + /** Read a raw Varint from the stream. */ + public long readRawVarint64() throws IOException { + int shift = 0; + long result = 0; + while (shift < 64) { + final byte b = readRawByte(); + result |= (long)(b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + throw InvalidProtocolBufferException.malformedVarint(); + } + + /** Read a 32-bit little-endian integer from the stream. */ + public int readRawLittleEndian32() throws IOException { + final byte b1 = readRawByte(); + final byte b2 = readRawByte(); + final byte b3 = readRawByte(); + final byte b4 = readRawByte(); + return (((int)b1 & 0xff) ) | + (((int)b2 & 0xff) << 8) | + (((int)b3 & 0xff) << 16) | + (((int)b4 & 0xff) << 24); + } + + /** Read a 64-bit little-endian integer from the stream. */ + public long readRawLittleEndian64() throws IOException { + final byte b1 = readRawByte(); + final byte b2 = readRawByte(); + final byte b3 = readRawByte(); + final byte b4 = readRawByte(); + final byte b5 = readRawByte(); + final byte b6 = readRawByte(); + final byte b7 = readRawByte(); + final byte b8 = readRawByte(); + return (((long)b1 & 0xff) ) | + (((long)b2 & 0xff) << 8) | + (((long)b3 & 0xff) << 16) | + (((long)b4 & 0xff) << 24) | + (((long)b5 & 0xff) << 32) | + (((long)b6 & 0xff) << 40) | + (((long)b7 & 0xff) << 48) | + (((long)b8 & 0xff) << 56); + } + + /** + * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers + * into values that can be efficiently encoded with varint. (Otherwise, + * negative values must be sign-extended to 64 bits to be varint encoded, + * thus always taking 10 bytes on the wire.) + * + * @param n An unsigned 32-bit integer, stored in a signed int because + * Java has no explicit unsigned support. + * @return A signed 32-bit integer. + */ + public static int decodeZigZag32(final int n) { + return (n >>> 1) ^ -(n & 1); + } + + /** + * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers + * into values that can be efficiently encoded with varint. (Otherwise, + * negative values must be sign-extended to 64 bits to be varint encoded, + * thus always taking 10 bytes on the wire.) + * + * @param n An unsigned 64-bit integer, stored in a signed int because + * Java has no explicit unsigned support. + * @return A signed 64-bit integer. + */ + public static long decodeZigZag64(final long n) { + return (n >>> 1) ^ -(n & 1); + } + + // ----------------------------------------------------------------- + + private final byte[] buffer; + private int bufferSize; + private int bufferSizeAfterLimit; + private int bufferPos; + private final RandomAccessFile raf; + private int lastTag; + + /** + * The total number of bytes read before the current buffer. The total + * bytes read up to the current position can be computed as + * {@code totalBytesRetired + bufferPos}. This value may be negative if + * reading started in the middle of the current buffer (e.g. if the + * constructor that takes a byte array and an offset was used). + */ + private int totalBytesRetired; + + /** The absolute position of the end of the current message. */ + private int currentLimit = Integer.MAX_VALUE; + + /** See setRecursionLimit() */ + private int recursionDepth; + private int recursionLimit = DEFAULT_RECURSION_LIMIT; + + /** See setSizeLimit() */ + private int sizeLimit = DEFAULT_SIZE_LIMIT; + + private static final int DEFAULT_RECURSION_LIMIT = 64; + private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB + private static final int BUFFER_SIZE_DEF = 4096; + private int BUFFER_SIZE = BUFFER_SIZE_DEF; + + + private CodedInputStreamRAF(final RandomAccessFile raf, int bufferSize) { + BUFFER_SIZE = bufferSize; + buffer = new byte[BUFFER_SIZE]; + this.bufferSize = 0; + bufferPos = 0; + totalBytesRetired = 0; + this.raf = raf; + } + + /** + * Set the maximum message recursion depth. In order to prevent malicious + * messages from causing stack overflows, {@code CodedInputStream} limits + * how deeply messages may be nested. The default limit is 64. + * + * @return the old limit. + */ + public int setRecursionLimit(final int limit) { + if (limit < 0) { + throw new IllegalArgumentException( + "Recursion limit cannot be negative: " + limit); + } + final int oldLimit = recursionLimit; + recursionLimit = limit; + return oldLimit; + } + + /** + * Set the maximum message size. In order to prevent malicious + * messages from exhausting memory or causing integer overflows, + * {@code CodedInputStream} limits how large a message may be. + * The default limit is 64MB. You should set this limit as small + * as you can without harming your app's functionality. Note that + * size limits only apply when reading from an {@code InputStream}, not + * when constructed around a raw byte array (nor with + * {@link ByteString#newCodedInput}). + *

+ * If you want to read several messages from a single CodedInputStream, you + * could call {@link #resetSizeCounter()} after each one to avoid hitting the + * size limit. + * + * @return the old limit. + */ + public int setSizeLimit(final int limit) { + if (limit < 0) { + throw new IllegalArgumentException( + "Size limit cannot be negative: " + limit); + } + final int oldLimit = sizeLimit; + sizeLimit = limit; + return oldLimit; + } + + /** + * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). + */ + public void resetSizeCounter() { + totalBytesRetired = -bufferPos; + } + + /** + * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This + * is called when descending into a length-delimited embedded message. + * + *

Note that {@code pushLimit()} does NOT affect how many bytes the + * {@code CodedInputStream} reads from an underlying {@code InputStream} when + * refreshing its buffer. If you need to prevent reading past a certain + * point in the underlying {@code InputStream} (e.g. because you expect it to + * contain more data after the end of the message which you need to handle + * differently) then you must place a wrapper around you {@code InputStream} + * which limits the amount of data that can be read from it. + * + * @return the old limit. + */ + public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { + if (byteLimit < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + byteLimit += totalBytesRetired + bufferPos; + final int oldLimit = currentLimit; + if (byteLimit > oldLimit) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + currentLimit = byteLimit; + + recomputeBufferSizeAfterLimit(); + + return oldLimit; + } + + private void recomputeBufferSizeAfterLimit() { + bufferSize += bufferSizeAfterLimit; + final int bufferEnd = totalBytesRetired + bufferSize; + if (bufferEnd > currentLimit) { + // Limit is in current buffer. + bufferSizeAfterLimit = bufferEnd - currentLimit; + bufferSize -= bufferSizeAfterLimit; + } else { + bufferSizeAfterLimit = 0; + } + } + + /** + * Discards the current limit, returning to the previous limit. + * + * @param oldLimit The old limit, as returned by {@code pushLimit}. + */ + public void popLimit(final int oldLimit) { + currentLimit = oldLimit; + recomputeBufferSizeAfterLimit(); + } + + /** + * Returns the number of bytes to be read before the current limit. + * If no limit is set, returns -1. + */ + public int getBytesUntilLimit() { + if (currentLimit == Integer.MAX_VALUE) { + return -1; + } + + final int currentAbsolutePosition = totalBytesRetired + bufferPos; + return currentLimit - currentAbsolutePosition; + } + + /** + * Returns true if the stream has reached the end of the input. This is the + * case if either the end of the underlying input source has been reached or + * if the stream has reached a limit created using {@link #pushLimit(int)}. + */ + public boolean isAtEnd() throws IOException { + return bufferPos == bufferSize && !refillBuffer(false); + } + + /** + * The total bytes read up to the current position. Calling + * {@link #resetSizeCounter()} resets this value to zero. + */ + public int getTotalBytesRead() { + return totalBytesRetired + bufferPos; + } + + /** + * Called with {@code this.buffer} is empty to read more bytes from the + * input. If {@code mustSucceed} is true, refillBuffer() gurantees that + * either there will be at least one byte in the buffer when it returns + * or it will throw an exception. If {@code mustSucceed} is false, + * refillBuffer() returns false if no more bytes were available. + */ + private boolean refillBuffer(final boolean mustSucceed) throws IOException { + if (bufferPos < bufferSize) { + throw new IllegalStateException( + "refillBuffer() called when buffer wasn't empty."); + } + + if (totalBytesRetired + bufferSize == currentLimit) { + // Oops, we hit a limit. + if (mustSucceed) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else { + return false; + } + } + + totalBytesRetired += bufferSize; + + bufferPos = 0; + // osmand change + bufferSize = raf.read(buffer); + if (bufferSize == 0 || bufferSize < -1) { + throw new IllegalStateException( + "InputStream#read(byte[]) returned invalid result: " + bufferSize + + "\nThe InputStream implementation is buggy."); + } + if (bufferSize == -1) { + bufferSize = 0; + if (mustSucceed) { + throw InvalidProtocolBufferException.truncatedMessage(); + } else { + return false; + } + } else { + recomputeBufferSizeAfterLimit(); + final int totalBytesRead = + totalBytesRetired + bufferSize + bufferSizeAfterLimit; + if (totalBytesRead > sizeLimit || totalBytesRead < 0) { + throw InvalidProtocolBufferException.sizeLimitExceeded(); + } + return true; + } + } + + /** + * Read one byte from the input. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + public byte readRawByte() throws IOException { + if (bufferPos == bufferSize) { + refillBuffer(true); + } + return buffer[bufferPos++]; + } + + /** + * Read a fixed size of bytes from the input. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + public byte[] readRawBytes(final int size) throws IOException { + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + + if (totalBytesRetired + bufferPos + size > currentLimit) { + // Read to the end of the stream anyway. + skipRawBytes(currentLimit - totalBytesRetired - bufferPos); + // Then fail. + throw InvalidProtocolBufferException.truncatedMessage(); + } + + if (size <= bufferSize - bufferPos) { + // We have all the bytes we need already. + final byte[] bytes = new byte[size]; + System.arraycopy(buffer, bufferPos, bytes, 0, size); + bufferPos += size; + return bytes; + } else if (size < BUFFER_SIZE) { + // Reading more bytes than are in the buffer, but not an excessive number + // of bytes. We can safely allocate the resulting array ahead of time. + + // First copy what we have. + final byte[] bytes = new byte[size]; + int pos = bufferSize - bufferPos; + System.arraycopy(buffer, bufferPos, bytes, 0, pos); + bufferPos = bufferSize; + + // We want to use refillBuffer() and then copy from the buffer into our + // byte array rather than reading directly into our byte array because + // the input may be unbuffered. + refillBuffer(true); + + while (size - pos > bufferSize) { + System.arraycopy(buffer, 0, bytes, pos, bufferSize); + pos += bufferSize; + bufferPos = bufferSize; + refillBuffer(true); + } + + System.arraycopy(buffer, 0, bytes, pos, size - pos); + bufferPos = size - pos; + + return bytes; + } else { + // The size is very large. For security reasons, we can't allocate the + // entire byte array yet. The size comes directly from the input, so a + // maliciously-crafted message could provide a bogus very large size in + // order to trick the app into allocating a lot of memory. We avoid this + // by allocating and reading only a small chunk at a time, so that the + // malicious message must actually *be* extremely large to cause + // problems. Meanwhile, we limit the allowed size of a message elsewhere. + + // Remember the buffer markers since we'll have to copy the bytes out of + // it later. + final int originalBufferPos = bufferPos; + final int originalBufferSize = bufferSize; + + // Mark the current buffer consumed. + totalBytesRetired += bufferSize; + bufferPos = 0; + bufferSize = 0; + + // Read all the rest of the bytes we need. + int sizeLeft = size - (originalBufferSize - originalBufferPos); + final List chunks = new ArrayList(); + + while (sizeLeft > 0) { + final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; + int pos = 0; + while (pos < chunk.length) { + // osmand change + final int n = raf.read(chunk, pos, chunk.length - pos); + if (n == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + totalBytesRetired += n; + pos += n; + } + sizeLeft -= chunk.length; + chunks.add(chunk); + } + + // OK, got everything. Now concatenate it all into one buffer. + final byte[] bytes = new byte[size]; + + // Start by copying the leftover bytes from this.buffer. + int pos = originalBufferSize - originalBufferPos; + System.arraycopy(buffer, originalBufferPos, bytes, 0, pos); + + // And now all the chunks. + for (final byte[] chunk : chunks) { + System.arraycopy(chunk, 0, bytes, pos, chunk.length); + pos += chunk.length; + } + + // Done. + return bytes; + } + } + + /** + * Reads and discards {@code size} bytes. + * + * @throws InvalidProtocolBufferException The end of the stream or the current + * limit was reached. + */ + public void skipRawBytes(final int size) throws IOException { + if (size < 0) { + throw InvalidProtocolBufferException.negativeSize(); + } + + if (totalBytesRetired + bufferPos + size > currentLimit) { + // Read to the end of the stream anyway. + skipRawBytes(currentLimit - totalBytesRetired - bufferPos); + // Then fail. + throw InvalidProtocolBufferException.truncatedMessage(); + } + + if (size <= bufferSize - bufferPos) { + // We have all the bytes we need already. + bufferPos += size; + } else { + // Skipping more bytes than are in the buffer. First skip what we have. + int pos = bufferSize - bufferPos; + totalBytesRetired += bufferSize; + bufferPos = 0; + bufferSize = 0; + + // Then skip directly from the InputStream for the rest. + while (pos < size) { + // osmand change + final int n = raf.skipBytes(size - pos); + if (n <= 0) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + pos += n; + totalBytesRetired += n; + } + } + } + + // osmand change + public void seek(long pointer) throws IOException{ + if(pointer - totalBytesRetired >= 0 && pointer - totalBytesRetired < bufferSize){ + if (pointer > currentLimit) { + // Then fail. + throw InvalidProtocolBufferException.truncatedMessage(); + } + bufferPos = (int) (pointer - totalBytesRetired); + } else { + totalBytesRetired = (int) pointer; + bufferSizeAfterLimit = 0; + raf.seek(pointer); + bufferPos = 0; + bufferSize = 0; + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java b/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java new file mode 100644 index 0000000000..6e81b981d9 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java @@ -0,0 +1,1040 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +/** + * Encodes and writes protocol message fields. + * + *

This class contains two kinds of methods: methods that write specific + * protocol message constructs and field types (e.g. {@link #writeTag} and + * {@link #writeInt32}) and methods that write low-level values (e.g. + * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are + * writing encoded protocol messages, you should use the former methods, but if + * you are writing some other format of your own design, use the latter. + * + *

This class is totally unsynchronized. + * + * @author kneton@google.com Kenton Varda + */ +public final class CodedOutputStream { + private final byte[] buffer; + private final int limit; + private int position; + // + Change + private long writtenBytes = 0; + + private final OutputStream output; + + /** + * The buffer size used in {@link #newInstance(OutputStream)}. + */ + public static final int DEFAULT_BUFFER_SIZE = 4096; + + /** + * Returns the buffer size to efficiently write dataLength bytes to this + * CodedOutputStream. Used by AbstractMessageLite. + * + * @return the buffer size to efficiently write dataLength bytes to this + * CodedOutputStream. + */ + static int computePreferredBufferSize(int dataLength) { + if (dataLength > DEFAULT_BUFFER_SIZE) return DEFAULT_BUFFER_SIZE; + return dataLength; + } + + private CodedOutputStream(final byte[] buffer, final int offset, + final int length) { + output = null; + this.buffer = buffer; + position = offset; + limit = offset + length; + } + + private CodedOutputStream(final OutputStream output, final byte[] buffer) { + this.output = output; + this.buffer = buffer; + position = 0; + limit = buffer.length; + } + + /** + * Create a new {@code CodedOutputStream} wrapping the given + * {@code OutputStream}. + */ + public static CodedOutputStream newInstance(final OutputStream output) { + return newInstance(output, DEFAULT_BUFFER_SIZE); + } + + /** + * Create a new {@code CodedOutputStream} wrapping the given + * {@code OutputStream} with a given buffer size. + */ + public static CodedOutputStream newInstance(final OutputStream output, + final int bufferSize) { + return new CodedOutputStream(output, new byte[bufferSize]); + } + + /** + * Create a new {@code CodedOutputStream} that writes directly to the given + * byte array. If more bytes are written than fit in the array, + * {@link OutOfSpaceException} will be thrown. Writing directly to a flat + * array is faster than writing to an {@code OutputStream}. See also + * {@link ByteString#newCodedBuilder}. + */ + public static CodedOutputStream newInstance(final byte[] flatArray) { + return newInstance(flatArray, 0, flatArray.length); + } + + /** + * Create a new {@code CodedOutputStream} that writes directly to the given + * byte array slice. If more bytes are written than fit in the slice, + * {@link OutOfSpaceException} will be thrown. Writing directly to a flat + * array is faster than writing to an {@code OutputStream}. See also + * {@link ByteString#newCodedBuilder}. + */ + public static CodedOutputStream newInstance(final byte[] flatArray, + final int offset, + final int length) { + return new CodedOutputStream(flatArray, offset, length); + } + + // ----------------------------------------------------------------- + + /** Write a {@code double} field, including tag, to the stream. */ + public void writeDouble(final int fieldNumber, final double value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + writeDoubleNoTag(value); + } + + /** Write a {@code float} field, including tag, to the stream. */ + public void writeFloat(final int fieldNumber, final float value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + writeFloatNoTag(value); + } + + /** Write a {@code uint64} field, including tag, to the stream. */ + public void writeUInt64(final int fieldNumber, final long value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeUInt64NoTag(value); + } + + /** Write an {@code int64} field, including tag, to the stream. */ + public void writeInt64(final int fieldNumber, final long value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeInt64NoTag(value); + } + + /** Write an {@code int32} field, including tag, to the stream. */ + public void writeInt32(final int fieldNumber, final int value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeInt32NoTag(value); + } + + /** Write a {@code fixed64} field, including tag, to the stream. */ + public void writeFixed64(final int fieldNumber, final long value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + writeFixed64NoTag(value); + } + + /** Write a {@code fixed32} field, including tag, to the stream. */ + public void writeFixed32(final int fieldNumber, final int value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + writeFixed32NoTag(value); + } + + /** Write a {@code bool} field, including tag, to the stream. */ + public void writeBool(final int fieldNumber, final boolean value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeBoolNoTag(value); + } + + /** Write a {@code string} field, including tag, to the stream. */ + public void writeString(final int fieldNumber, final String value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeStringNoTag(value); + } + + /** Write a {@code group} field, including tag, to the stream. */ + public void writeGroup(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); + writeGroupNoTag(value); + writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); + } + + /** + * Write a group represented by an {@link UnknownFieldSet}. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #writeGroup}. + */ + @Deprecated + public void writeUnknownGroup(final int fieldNumber, + final MessageLite value) + throws IOException { + writeGroup(fieldNumber, value); + } + + /** Write an embedded message field, including tag, to the stream. */ + public void writeMessage(final int fieldNumber, final MessageLite value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeMessageNoTag(value); + } + + /** Write a {@code bytes} field, including tag, to the stream. */ + public void writeBytes(final int fieldNumber, final ByteString value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED); + writeBytesNoTag(value); + } + + /** Write a {@code uint32} field, including tag, to the stream. */ + public void writeUInt32(final int fieldNumber, final int value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeUInt32NoTag(value); + } + + /** + * Write an enum field, including tag, to the stream. Caller is responsible + * for converting the enum value to its numeric value. + */ + public void writeEnum(final int fieldNumber, final int value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeEnumNoTag(value); + } + + /** Write an {@code sfixed32} field, including tag, to the stream. */ + public void writeSFixed32(final int fieldNumber, final int value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32); + writeSFixed32NoTag(value); + } + + /** Write an {@code sfixed64} field, including tag, to the stream. */ + public void writeSFixed64(final int fieldNumber, final long value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64); + writeSFixed64NoTag(value); + } + + /** Write an {@code sint32} field, including tag, to the stream. */ + public void writeSInt32(final int fieldNumber, final int value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeSInt32NoTag(value); + } + + /** Write an {@code sint64} field, including tag, to the stream. */ + public void writeSInt64(final int fieldNumber, final long value) + throws IOException { + writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT); + writeSInt64NoTag(value); + } + + /** + * Write a MessageSet extension field to the stream. For historical reasons, + * the wire format differs from normal fields. + */ + public void writeMessageSetExtension(final int fieldNumber, + final MessageLite value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + /** + * Write an unparsed MessageSet extension field to the stream. For + * historical reasons, the wire format differs from normal fields. + */ + public void writeRawMessageSetExtension(final int fieldNumber, + final ByteString value) + throws IOException { + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP); + writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber); + writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value); + writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP); + } + + // ----------------------------------------------------------------- + + /** Write a {@code double} field to the stream. */ + public void writeDoubleNoTag(final double value) throws IOException { + writeRawLittleEndian64(Double.doubleToRawLongBits(value)); + } + + /** Write a {@code float} field to the stream. */ + public void writeFloatNoTag(final float value) throws IOException { + writeRawLittleEndian32(Float.floatToRawIntBits(value)); + } + + /** Write a {@code uint64} field to the stream. */ + public void writeUInt64NoTag(final long value) throws IOException { + writeRawVarint64(value); + } + + /** Write an {@code int64} field to the stream. */ + public void writeInt64NoTag(final long value) throws IOException { + writeRawVarint64(value); + } + + /** Write an {@code int32} field to the stream. */ + public void writeInt32NoTag(final int value) throws IOException { + if (value >= 0) { + writeRawVarint32(value); + } else { + // Must sign-extend. + writeRawVarint64(value); + } + } + + /** Write a {@code fixed64} field to the stream. */ + public void writeFixed64NoTag(final long value) throws IOException { + writeRawLittleEndian64(value); + } + + /** Write a {@code fixed32} field to the stream. */ + public void writeFixed32NoTag(final int value) throws IOException { + writeRawLittleEndian32(value); + } + + /** Write a {@code bool} field to the stream. */ + public void writeBoolNoTag(final boolean value) throws IOException { + writeRawByte(value ? 1 : 0); + } + + /** Write a {@code string} field to the stream. */ + public void writeStringNoTag(final String value) throws IOException { + // Unfortunately there does not appear to be any way to tell Java to encode + // UTF-8 directly into our buffer, so we have to let it create its own byte + // array and then copy. + final byte[] bytes = value.getBytes("UTF-8"); + writeRawVarint32(bytes.length); + writeRawBytes(bytes); + } + + /** Write a {@code group} field to the stream. */ + public void writeGroupNoTag(final MessageLite value) throws IOException { + value.writeTo(this); + } + + /** + * Write a group represented by an {@link UnknownFieldSet}. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #writeGroupNoTag}. + */ + @Deprecated + public void writeUnknownGroupNoTag(final MessageLite value) + throws IOException { + writeGroupNoTag(value); + } + + /** Write an embedded message field to the stream. */ + public void writeMessageNoTag(final MessageLite value) throws IOException { + writeRawVarint32(value.getSerializedSize()); + value.writeTo(this); + } + + /** Write a {@code bytes} field to the stream. */ + public void writeBytesNoTag(final ByteString value) throws IOException { + final byte[] bytes = value.toByteArray(); + writeRawVarint32(bytes.length); + writeRawBytes(bytes); + } + + /** Write a {@code uint32} field to the stream. */ + public void writeUInt32NoTag(final int value) throws IOException { + writeRawVarint32(value); + } + + /** + * Write an enum field to the stream. Caller is responsible + * for converting the enum value to its numeric value. + */ + public void writeEnumNoTag(final int value) throws IOException { + writeRawVarint32(value); + } + + /** Write an {@code sfixed32} field to the stream. */ + public void writeSFixed32NoTag(final int value) throws IOException { + writeRawLittleEndian32(value); + } + + /** Write an {@code sfixed64} field to the stream. */ + public void writeSFixed64NoTag(final long value) throws IOException { + writeRawLittleEndian64(value); + } + + /** Write an {@code sint32} field to the stream. */ + public void writeSInt32NoTag(final int value) throws IOException { + writeRawVarint32(encodeZigZag32(value)); + } + + /** Write an {@code sint64} field to the stream. */ + public void writeSInt64NoTag(final long value) throws IOException { + writeRawVarint64(encodeZigZag64(value)); + } + + // ================================================================= + + /** + * Compute the number of bytes that would be needed to encode a + * {@code double} field, including tag. + */ + public static int computeDoubleSize(final int fieldNumber, + final double value) { + return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code float} field, including tag. + */ + public static int computeFloatSize(final int fieldNumber, final float value) { + return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code uint64} field, including tag. + */ + public static int computeUInt64Size(final int fieldNumber, final long value) { + return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code int64} field, including tag. + */ + public static int computeInt64Size(final int fieldNumber, final long value) { + return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code int32} field, including tag. + */ + public static int computeInt32Size(final int fieldNumber, final int value) { + return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code fixed64} field, including tag. + */ + public static int computeFixed64Size(final int fieldNumber, + final long value) { + return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code fixed32} field, including tag. + */ + public static int computeFixed32Size(final int fieldNumber, + final int value) { + return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code bool} field, including tag. + */ + public static int computeBoolSize(final int fieldNumber, + final boolean value) { + return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code string} field, including tag. + */ + public static int computeStringSize(final int fieldNumber, + final String value) { + return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code group} field, including tag. + */ + public static int computeGroupSize(final int fieldNumber, + final MessageLite value) { + return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code group} field represented by an {@code UnknownFieldSet}, including + * tag. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #computeGroupSize}. + */ + @Deprecated + public static int computeUnknownGroupSize(final int fieldNumber, + final MessageLite value) { + return computeGroupSize(fieldNumber, value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * embedded message field, including tag. + */ + public static int computeMessageSize(final int fieldNumber, + final MessageLite value) { + return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code bytes} field, including tag. + */ + public static int computeBytesSize(final int fieldNumber, + final ByteString value) { + return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code uint32} field, including tag. + */ + public static int computeUInt32Size(final int fieldNumber, final int value) { + return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * enum field, including tag. Caller is responsible for converting the + * enum value to its numeric value. + */ + public static int computeEnumSize(final int fieldNumber, final int value) { + return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sfixed32} field, including tag. + */ + public static int computeSFixed32Size(final int fieldNumber, + final int value) { + return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sfixed64} field, including tag. + */ + public static int computeSFixed64Size(final int fieldNumber, + final long value) { + return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sint32} field, including tag. + */ + public static int computeSInt32Size(final int fieldNumber, final int value) { + return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sint64} field, including tag. + */ + public static int computeSInt64Size(final int fieldNumber, final long value) { + return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * MessageSet extension to the stream. For historical reasons, + * the wire format differs from normal fields. + */ + public static int computeMessageSetExtensionSize( + final int fieldNumber, final MessageLite value) { + return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 + + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) + + computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * unparsed MessageSet extension field to the stream. For + * historical reasons, the wire format differs from normal fields. + */ + public static int computeRawMessageSetExtensionSize( + final int fieldNumber, final ByteString value) { + return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 + + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) + + computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value); + } + + // ----------------------------------------------------------------- + + /** + * Compute the number of bytes that would be needed to encode a + * {@code double} field, including tag. + */ + public static int computeDoubleSizeNoTag(final double value) { + return LITTLE_ENDIAN_64_SIZE; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code float} field, including tag. + */ + public static int computeFloatSizeNoTag(final float value) { + return LITTLE_ENDIAN_32_SIZE; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code uint64} field, including tag. + */ + public static int computeUInt64SizeNoTag(final long value) { + return computeRawVarint64Size(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code int64} field, including tag. + */ + public static int computeInt64SizeNoTag(final long value) { + return computeRawVarint64Size(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code int32} field, including tag. + */ + public static int computeInt32SizeNoTag(final int value) { + if (value >= 0) { + return computeRawVarint32Size(value); + } else { + // Must sign-extend. + return 10; + } + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code fixed64} field. + */ + public static int computeFixed64SizeNoTag(final long value) { + return LITTLE_ENDIAN_64_SIZE; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code fixed32} field. + */ + public static int computeFixed32SizeNoTag(final int value) { + return LITTLE_ENDIAN_32_SIZE; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code bool} field. + */ + public static int computeBoolSizeNoTag(final boolean value) { + return 1; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code string} field. + */ + public static int computeStringSizeNoTag(final String value) { + try { + final byte[] bytes = value.getBytes("UTF-8"); + return computeRawVarint32Size(bytes.length) + + bytes.length; + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 not supported.", e); + } + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code group} field. + */ + public static int computeGroupSizeNoTag(final MessageLite value) { + return value.getSerializedSize(); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code group} field represented by an {@code UnknownFieldSet}, including + * tag. + * + * @deprecated UnknownFieldSet now implements MessageLite, so you can just + * call {@link #computeUnknownGroupSizeNoTag}. + */ + @Deprecated + public static int computeUnknownGroupSizeNoTag(final MessageLite value) { + return computeGroupSizeNoTag(value); + } + + /** + * Compute the number of bytes that would be needed to encode an embedded + * message field. + */ + public static int computeMessageSizeNoTag(final MessageLite value) { + final int size = value.getSerializedSize(); + return computeRawVarint32Size(size) + size; + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code bytes} field. + */ + public static int computeBytesSizeNoTag(final ByteString value) { + return computeRawVarint32Size(value.size()) + + value.size(); + } + + /** + * Compute the number of bytes that would be needed to encode a + * {@code uint32} field. + */ + public static int computeUInt32SizeNoTag(final int value) { + return computeRawVarint32Size(value); + } + + /** + * Compute the number of bytes that would be needed to encode an enum field. + * Caller is responsible for converting the enum value to its numeric value. + */ + public static int computeEnumSizeNoTag(final int value) { + return computeRawVarint32Size(value); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sfixed32} field. + */ + public static int computeSFixed32SizeNoTag(final int value) { + return LITTLE_ENDIAN_32_SIZE; + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sfixed64} field. + */ + public static int computeSFixed64SizeNoTag(final long value) { + return LITTLE_ENDIAN_64_SIZE; + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sint32} field. + */ + public static int computeSInt32SizeNoTag(final int value) { + return computeRawVarint32Size(encodeZigZag32(value)); + } + + /** + * Compute the number of bytes that would be needed to encode an + * {@code sint64} field. + */ + public static int computeSInt64SizeNoTag(final long value) { + return computeRawVarint64Size(encodeZigZag64(value)); + } + + // ================================================================= + + /** + * Internal helper that writes the current buffer to the output. The + * buffer position is reset to its initial value when this returns. + */ + private void refreshBuffer() throws IOException { + if (output == null) { + // We're writing to a single buffer. + throw new OutOfSpaceException(); + } + + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + output.write(buffer, 0, position); + writtenBytes += position; + position = 0; + } + + /** + * Flushes the stream and forces any buffered bytes to be written. This + * does not flush the underlying OutputStream. + */ + public void flush() throws IOException { + if (output != null) { + refreshBuffer(); + } + } + + /** + * @return current offset in the output file + */ + public long getWrittenBytes() { + return writtenBytes + position; + } + + /** + * If writing to a flat array, return the space left in the array. + * Otherwise, throws {@code UnsupportedOperationException}. + */ + public int spaceLeft() { + if (output == null) { + return limit - position; + } else { + throw new UnsupportedOperationException( + "spaceLeft() can only be called on CodedOutputStreams that are " + + "writing to a flat array."); + } + } + + /** + * Verifies that {@link #spaceLeft()} returns zero. It's common to create + * a byte array that is exactly big enough to hold a message, then write to + * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} + * after writing verifies that the message was actually as big as expected, + * which can help catch bugs. + */ + public void checkNoSpaceLeft() { + if (spaceLeft() != 0) { + throw new IllegalStateException( + "Did not write as much data as expected."); + } + } + + /** + * If you create a CodedOutputStream around a simple flat array, you must + * not attempt to write more bytes than the array has space. Otherwise, + * this exception will be thrown. + */ + public static class OutOfSpaceException extends IOException { + private static final long serialVersionUID = -6947486886997889499L; + + OutOfSpaceException() { + super("CodedOutputStream was writing to a flat byte array and ran " + + "out of space."); + } + } + + /** Write a single byte. */ + public void writeRawByte(final byte value) throws IOException { + if (position == limit) { + refreshBuffer(); + } + + buffer[position++] = value; + } + + /** Write a single byte, represented by an integer value. */ + public void writeRawByte(final int value) throws IOException { + writeRawByte((byte) value); + } + + /** Write an array of bytes. */ + public void writeRawBytes(final byte[] value) throws IOException { + writeRawBytes(value, 0, value.length); + } + + /** Write part of an array of bytes. */ + public void writeRawBytes(final byte[] value, int offset, int length) + throws IOException { + if (limit - position >= length) { + // We have room in the current buffer. + System.arraycopy(value, offset, buffer, position, length); + position += length; + } else { + // Write extends past current buffer. Fill the rest of this buffer and + // flush. + final int bytesWritten = limit - position; + System.arraycopy(value, offset, buffer, position, bytesWritten); + offset += bytesWritten; + length -= bytesWritten; + position = limit; + refreshBuffer(); + + // Now deal with the rest. + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + if (length <= limit) { + // Fits in new buffer. + System.arraycopy(value, offset, buffer, 0, length); + position = length; + } else { + // Write is very big. Let's do it all at once. + output.write(value, offset, length); + writtenBytes += length; + } + } + } + + /** Encode and write a tag. */ + public void writeTag(final int fieldNumber, final int wireType) + throws IOException { + writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType)); + } + + /** Compute the number of bytes that would be needed to encode a tag. */ + public static int computeTagSize(final int fieldNumber) { + return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0)); + } + + /** + * Encode and write a varint. {@code value} is treated as + * unsigned, so it won't be sign-extended if negative. + */ + public void writeRawVarint32(int value) throws IOException { + while (true) { + if ((value & ~0x7F) == 0) { + writeRawByte(value); + return; + } else { + writeRawByte((value & 0x7F) | 0x80); + value >>>= 7; + } + } + } + + /** + * Compute the number of bytes that would be needed to encode a varint. + * {@code value} is treated as unsigned, so it won't be sign-extended if + * negative. + */ + public static int computeRawVarint32Size(final int value) { + if ((value & (0xffffffff << 7)) == 0) return 1; + if ((value & (0xffffffff << 14)) == 0) return 2; + if ((value & (0xffffffff << 21)) == 0) return 3; + if ((value & (0xffffffff << 28)) == 0) return 4; + return 5; + } + + /** Encode and write a varint. */ + public void writeRawVarint64(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + writeRawByte((int)value); + return; + } else { + writeRawByte(((int)value & 0x7F) | 0x80); + value >>>= 7; + } + } + } + + /** Compute the number of bytes that would be needed to encode a varint. */ + public static int computeRawVarint64Size(final long value) { + if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; + if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; + if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; + if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; + if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; + if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; + if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; + if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; + if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; + return 10; + } + + /** Write a little-endian 32-bit integer. */ + public void writeRawLittleEndian32(final int value) throws IOException { + writeRawByte((value ) & 0xFF); + writeRawByte((value >> 8) & 0xFF); + writeRawByte((value >> 16) & 0xFF); + writeRawByte((value >> 24) & 0xFF); + } + + public static final int LITTLE_ENDIAN_32_SIZE = 4; + + /** Write a little-endian 64-bit integer. */ + public void writeRawLittleEndian64(final long value) throws IOException { + writeRawByte((int)(value ) & 0xFF); + writeRawByte((int)(value >> 8) & 0xFF); + writeRawByte((int)(value >> 16) & 0xFF); + writeRawByte((int)(value >> 24) & 0xFF); + writeRawByte((int)(value >> 32) & 0xFF); + writeRawByte((int)(value >> 40) & 0xFF); + writeRawByte((int)(value >> 48) & 0xFF); + writeRawByte((int)(value >> 56) & 0xFF); + } + + public static final int LITTLE_ENDIAN_64_SIZE = 8; + + /** + * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers + * into values that can be efficiently encoded with varint. (Otherwise, + * negative values must be sign-extended to 64 bits to be varint encoded, + * thus always taking 10 bytes on the wire.) + * + * @param n A signed 32-bit integer. + * @return An unsigned 32-bit integer, stored in a signed int because + * Java has no explicit unsigned support. + */ + public static int encodeZigZag32(final int n) { + // Note: the right-shift must be arithmetic + return (n << 1) ^ (n >> 31); + } + + /** + * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers + * into values that can be efficiently encoded with varint. (Otherwise, + * negative values must be sign-extended to 64 bits to be varint encoded, + * thus always taking 10 bytes on the wire.) + * + * @param n A signed 64-bit integer. + * @return An unsigned 64-bit integer, stored in a signed int because + * Java has no explicit unsigned support. + */ + public static long encodeZigZag64(final long n) { + // Note: the right-shift must be arithmetic + return (n << 1) ^ (n >> 63); + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/DescriptorProtos.java b/OsmAnd-java/src/com/google/protobuf/DescriptorProtos.java new file mode 100644 index 0000000000..fcaea4368a --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/DescriptorProtos.java @@ -0,0 +1,9411 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto + +package com.google.protobuf; + +public final class DescriptorProtos { + private DescriptorProtos() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + public static final class FileDescriptorSet extends + com.google.protobuf.GeneratedMessage { + // Use FileDescriptorSet.newBuilder() to construct. + private FileDescriptorSet() { + initFields(); + } + private FileDescriptorSet(boolean noInit) {} + + private static final FileDescriptorSet defaultInstance; + public static FileDescriptorSet getDefaultInstance() { + return defaultInstance; + } + + @Override + public FileDescriptorSet getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_FileDescriptorSet_fieldAccessorTable; + } + + // repeated .google.protobuf.FileDescriptorProto file = 1; + public static final int FILE_FIELD_NUMBER = 1; + private java.util.List file_ = + java.util.Collections.emptyList(); + public java.util.List getFileList() { + return file_; + } + public int getFileCount() { return file_.size(); } + public com.google.protobuf.DescriptorProtos.FileDescriptorProto getFile(int index) { + return file_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + for (com.google.protobuf.DescriptorProtos.FileDescriptorProto element : getFileList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (com.google.protobuf.DescriptorProtos.FileDescriptorProto element : getFileList()) { + output.writeMessage(1, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + for (com.google.protobuf.DescriptorProtos.FileDescriptorProto element : getFileList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorSet parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(com.google.protobuf.DescriptorProtos.FileDescriptorSet prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private com.google.protobuf.DescriptorProtos.FileDescriptorSet result; + + // Construct using com.google.protobuf.DescriptorProtos.FileDescriptorSet.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.google.protobuf.DescriptorProtos.FileDescriptorSet(); + return builder; + } + + @Override + protected com.google.protobuf.DescriptorProtos.FileDescriptorSet internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new com.google.protobuf.DescriptorProtos.FileDescriptorSet(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.google.protobuf.DescriptorProtos.FileDescriptorSet.getDescriptor(); + } + + @Override + public com.google.protobuf.DescriptorProtos.FileDescriptorSet getDefaultInstanceForType() { + return com.google.protobuf.DescriptorProtos.FileDescriptorSet.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public com.google.protobuf.DescriptorProtos.FileDescriptorSet build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.google.protobuf.DescriptorProtos.FileDescriptorSet buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public com.google.protobuf.DescriptorProtos.FileDescriptorSet buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.file_ != java.util.Collections.EMPTY_LIST) { + result.file_ = + java.util.Collections.unmodifiableList(result.file_); + } + com.google.protobuf.DescriptorProtos.FileDescriptorSet returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.protobuf.DescriptorProtos.FileDescriptorSet) { + return mergeFrom((com.google.protobuf.DescriptorProtos.FileDescriptorSet)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.protobuf.DescriptorProtos.FileDescriptorSet other) { + if (other == com.google.protobuf.DescriptorProtos.FileDescriptorSet.getDefaultInstance()) return this; + if (!other.file_.isEmpty()) { + if (result.file_.isEmpty()) { + result.file_ = new java.util.ArrayList(); + } + result.file_.addAll(other.file_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + com.google.protobuf.DescriptorProtos.FileDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.FileDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addFile(subBuilder.buildPartial()); + break; + } + } + } + } + + + // repeated .google.protobuf.FileDescriptorProto file = 1; + public java.util.List getFileList() { + return java.util.Collections.unmodifiableList(result.file_); + } + public int getFileCount() { + return result.getFileCount(); + } + public com.google.protobuf.DescriptorProtos.FileDescriptorProto getFile(int index) { + return result.getFile(index); + } + public Builder setFile(int index, com.google.protobuf.DescriptorProtos.FileDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.file_.set(index, value); + return this; + } + public Builder setFile(int index, com.google.protobuf.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + result.file_.set(index, builderForValue.build()); + return this; + } + public Builder addFile(com.google.protobuf.DescriptorProtos.FileDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.file_.isEmpty()) { + result.file_ = new java.util.ArrayList(); + } + result.file_.add(value); + return this; + } + public Builder addFile(com.google.protobuf.DescriptorProtos.FileDescriptorProto.Builder builderForValue) { + if (result.file_.isEmpty()) { + result.file_ = new java.util.ArrayList(); + } + result.file_.add(builderForValue.build()); + return this; + } + public Builder addAllFile( + java.lang.Iterable values) { + if (result.file_.isEmpty()) { + result.file_ = new java.util.ArrayList(); + } + super.addAll(values, result.file_); + return this; + } + public Builder clearFile() { + result.file_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:google.protobuf.FileDescriptorSet) + } + + static { + defaultInstance = new FileDescriptorSet(true); + com.google.protobuf.DescriptorProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + } + + public static final class FileDescriptorProto extends + com.google.protobuf.GeneratedMessage { + // Use FileDescriptorProto.newBuilder() to construct. + private FileDescriptorProto() { + initFields(); + } + private FileDescriptorProto(boolean noInit) {} + + private static final FileDescriptorProto defaultInstance; + public static FileDescriptorProto getDefaultInstance() { + return defaultInstance; + } + + @Override + public FileDescriptorProto getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_FileDescriptorProto_fieldAccessorTable; + } + + // optional string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string package = 2; + public static final int PACKAGE_FIELD_NUMBER = 2; + private boolean hasPackage; + private java.lang.String package_ = ""; + public boolean hasPackage() { return hasPackage; } + public java.lang.String getPackage() { return package_; } + + // repeated string dependency = 3; + public static final int DEPENDENCY_FIELD_NUMBER = 3; + private java.util.List dependency_ = + java.util.Collections.emptyList(); + public java.util.List getDependencyList() { + return dependency_; + } + public int getDependencyCount() { return dependency_.size(); } + public java.lang.String getDependency(int index) { + return dependency_.get(index); + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + public static final int MESSAGE_TYPE_FIELD_NUMBER = 4; + private java.util.List messageType_ = + java.util.Collections.emptyList(); + public java.util.List getMessageTypeList() { + return messageType_; + } + public int getMessageTypeCount() { return messageType_.size(); } + public com.google.protobuf.DescriptorProtos.DescriptorProto getMessageType(int index) { + return messageType_.get(index); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + public static final int ENUM_TYPE_FIELD_NUMBER = 5; + private java.util.List enumType_ = + java.util.Collections.emptyList(); + public java.util.List getEnumTypeList() { + return enumType_; + } + public int getEnumTypeCount() { return enumType_.size(); } + public com.google.protobuf.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + return enumType_.get(index); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + public static final int SERVICE_FIELD_NUMBER = 6; + private java.util.List service_ = + java.util.Collections.emptyList(); + public java.util.List getServiceList() { + return service_; + } + public int getServiceCount() { return service_.size(); } + public com.google.protobuf.DescriptorProtos.ServiceDescriptorProto getService(int index) { + return service_.get(index); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + public static final int EXTENSION_FIELD_NUMBER = 7; + private java.util.List extension_ = + java.util.Collections.emptyList(); + public java.util.List getExtensionList() { + return extension_; + } + public int getExtensionCount() { return extension_.size(); } + public com.google.protobuf.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + return extension_.get(index); + } + + // optional .google.protobuf.FileOptions options = 8; + public static final int OPTIONS_FIELD_NUMBER = 8; + private boolean hasOptions; + private com.google.protobuf.DescriptorProtos.FileOptions options_; + public boolean hasOptions() { return hasOptions; } + public com.google.protobuf.DescriptorProtos.FileOptions getOptions() { return options_; } + + private void initFields() { + options_ = com.google.protobuf.DescriptorProtos.FileOptions.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + for (com.google.protobuf.DescriptorProtos.DescriptorProto element : getMessageTypeList()) { + if (!element.isInitialized()) return false; + } + for (com.google.protobuf.DescriptorProtos.EnumDescriptorProto element : getEnumTypeList()) { + if (!element.isInitialized()) return false; + } + for (com.google.protobuf.DescriptorProtos.ServiceDescriptorProto element : getServiceList()) { + if (!element.isInitialized()) return false; + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getExtensionList()) { + if (!element.isInitialized()) return false; + } + if (hasOptions()) { + if (!getOptions().isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasPackage()) { + output.writeString(2, getPackage()); + } + for (java.lang.String element : getDependencyList()) { + output.writeString(3, element); + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto element : getMessageTypeList()) { + output.writeMessage(4, element); + } + for (com.google.protobuf.DescriptorProtos.EnumDescriptorProto element : getEnumTypeList()) { + output.writeMessage(5, element); + } + for (com.google.protobuf.DescriptorProtos.ServiceDescriptorProto element : getServiceList()) { + output.writeMessage(6, element); + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getExtensionList()) { + output.writeMessage(7, element); + } + if (hasOptions()) { + output.writeMessage(8, getOptions()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasPackage()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getPackage()); + } + { + int dataSize = 0; + for (java.lang.String element : getDependencyList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getDependencyList().size(); + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto element : getMessageTypeList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, element); + } + for (com.google.protobuf.DescriptorProtos.EnumDescriptorProto element : getEnumTypeList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + for (com.google.protobuf.DescriptorProtos.ServiceDescriptorProto element : getServiceList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getExtensionList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + if (hasOptions()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, getOptions()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.FileDescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(com.google.protobuf.DescriptorProtos.FileDescriptorProto prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private com.google.protobuf.DescriptorProtos.FileDescriptorProto result; + + // Construct using com.google.protobuf.DescriptorProtos.FileDescriptorProto.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.google.protobuf.DescriptorProtos.FileDescriptorProto(); + return builder; + } + + @Override + protected com.google.protobuf.DescriptorProtos.FileDescriptorProto internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new com.google.protobuf.DescriptorProtos.FileDescriptorProto(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.google.protobuf.DescriptorProtos.FileDescriptorProto.getDescriptor(); + } + + @Override + public com.google.protobuf.DescriptorProtos.FileDescriptorProto getDefaultInstanceForType() { + return com.google.protobuf.DescriptorProtos.FileDescriptorProto.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public com.google.protobuf.DescriptorProtos.FileDescriptorProto build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.google.protobuf.DescriptorProtos.FileDescriptorProto buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public com.google.protobuf.DescriptorProtos.FileDescriptorProto buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.dependency_ != java.util.Collections.EMPTY_LIST) { + result.dependency_ = + java.util.Collections.unmodifiableList(result.dependency_); + } + if (result.messageType_ != java.util.Collections.EMPTY_LIST) { + result.messageType_ = + java.util.Collections.unmodifiableList(result.messageType_); + } + if (result.enumType_ != java.util.Collections.EMPTY_LIST) { + result.enumType_ = + java.util.Collections.unmodifiableList(result.enumType_); + } + if (result.service_ != java.util.Collections.EMPTY_LIST) { + result.service_ = + java.util.Collections.unmodifiableList(result.service_); + } + if (result.extension_ != java.util.Collections.EMPTY_LIST) { + result.extension_ = + java.util.Collections.unmodifiableList(result.extension_); + } + com.google.protobuf.DescriptorProtos.FileDescriptorProto returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.protobuf.DescriptorProtos.FileDescriptorProto) { + return mergeFrom((com.google.protobuf.DescriptorProtos.FileDescriptorProto)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.protobuf.DescriptorProtos.FileDescriptorProto other) { + if (other == com.google.protobuf.DescriptorProtos.FileDescriptorProto.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasPackage()) { + setPackage(other.getPackage()); + } + if (!other.dependency_.isEmpty()) { + if (result.dependency_.isEmpty()) { + result.dependency_ = new java.util.ArrayList(); + } + result.dependency_.addAll(other.dependency_); + } + if (!other.messageType_.isEmpty()) { + if (result.messageType_.isEmpty()) { + result.messageType_ = new java.util.ArrayList(); + } + result.messageType_.addAll(other.messageType_); + } + if (!other.enumType_.isEmpty()) { + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + result.enumType_.addAll(other.enumType_); + } + if (!other.service_.isEmpty()) { + if (result.service_.isEmpty()) { + result.service_ = new java.util.ArrayList(); + } + result.service_.addAll(other.service_); + } + if (!other.extension_.isEmpty()) { + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + result.extension_.addAll(other.extension_); + } + if (other.hasOptions()) { + mergeOptions(other.getOptions()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + setPackage(input.readString()); + break; + } + case 26: { + addDependency(input.readString()); + break; + } + case 34: { + com.google.protobuf.DescriptorProtos.DescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.DescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addMessageType(subBuilder.buildPartial()); + break; + } + case 42: { + com.google.protobuf.DescriptorProtos.EnumDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.EnumDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addEnumType(subBuilder.buildPartial()); + break; + } + case 50: { + com.google.protobuf.DescriptorProtos.ServiceDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.ServiceDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addService(subBuilder.buildPartial()); + break; + } + case 58: { + com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.FieldDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addExtension(subBuilder.buildPartial()); + break; + } + case 66: { + com.google.protobuf.DescriptorProtos.FileOptions.Builder subBuilder = com.google.protobuf.DescriptorProtos.FileOptions.newBuilder(); + if (hasOptions()) { + subBuilder.mergeFrom(getOptions()); + } + input.readMessage(subBuilder, extensionRegistry); + setOptions(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string package = 2; + public boolean hasPackage() { + return result.hasPackage(); + } + public java.lang.String getPackage() { + return result.getPackage(); + } + public Builder setPackage(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPackage = true; + result.package_ = value; + return this; + } + public Builder clearPackage() { + result.hasPackage = false; + result.package_ = getDefaultInstance().getPackage(); + return this; + } + + // repeated string dependency = 3; + public java.util.List getDependencyList() { + return java.util.Collections.unmodifiableList(result.dependency_); + } + public int getDependencyCount() { + return result.getDependencyCount(); + } + public java.lang.String getDependency(int index) { + return result.getDependency(index); + } + public Builder setDependency(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.dependency_.set(index, value); + return this; + } + public Builder addDependency(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.dependency_.isEmpty()) { + result.dependency_ = new java.util.ArrayList(); + } + result.dependency_.add(value); + return this; + } + public Builder addAllDependency( + java.lang.Iterable values) { + if (result.dependency_.isEmpty()) { + result.dependency_ = new java.util.ArrayList(); + } + super.addAll(values, result.dependency_); + return this; + } + public Builder clearDependency() { + result.dependency_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + public java.util.List getMessageTypeList() { + return java.util.Collections.unmodifiableList(result.messageType_); + } + public int getMessageTypeCount() { + return result.getMessageTypeCount(); + } + public com.google.protobuf.DescriptorProtos.DescriptorProto getMessageType(int index) { + return result.getMessageType(index); + } + public Builder setMessageType(int index, com.google.protobuf.DescriptorProtos.DescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.messageType_.set(index, value); + return this; + } + public Builder setMessageType(int index, com.google.protobuf.DescriptorProtos.DescriptorProto.Builder builderForValue) { + result.messageType_.set(index, builderForValue.build()); + return this; + } + public Builder addMessageType(com.google.protobuf.DescriptorProtos.DescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.messageType_.isEmpty()) { + result.messageType_ = new java.util.ArrayList(); + } + result.messageType_.add(value); + return this; + } + public Builder addMessageType(com.google.protobuf.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (result.messageType_.isEmpty()) { + result.messageType_ = new java.util.ArrayList(); + } + result.messageType_.add(builderForValue.build()); + return this; + } + public Builder addAllMessageType( + java.lang.Iterable values) { + if (result.messageType_.isEmpty()) { + result.messageType_ = new java.util.ArrayList(); + } + super.addAll(values, result.messageType_); + return this; + } + public Builder clearMessageType() { + result.messageType_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + public java.util.List getEnumTypeList() { + return java.util.Collections.unmodifiableList(result.enumType_); + } + public int getEnumTypeCount() { + return result.getEnumTypeCount(); + } + public com.google.protobuf.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + return result.getEnumType(index); + } + public Builder setEnumType(int index, com.google.protobuf.DescriptorProtos.EnumDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.enumType_.set(index, value); + return this; + } + public Builder setEnumType(int index, com.google.protobuf.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + result.enumType_.set(index, builderForValue.build()); + return this; + } + public Builder addEnumType(com.google.protobuf.DescriptorProtos.EnumDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + result.enumType_.add(value); + return this; + } + public Builder addEnumType(com.google.protobuf.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + result.enumType_.add(builderForValue.build()); + return this; + } + public Builder addAllEnumType( + java.lang.Iterable values) { + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + super.addAll(values, result.enumType_); + return this; + } + public Builder clearEnumType() { + result.enumType_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + public java.util.List getServiceList() { + return java.util.Collections.unmodifiableList(result.service_); + } + public int getServiceCount() { + return result.getServiceCount(); + } + public com.google.protobuf.DescriptorProtos.ServiceDescriptorProto getService(int index) { + return result.getService(index); + } + public Builder setService(int index, com.google.protobuf.DescriptorProtos.ServiceDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.service_.set(index, value); + return this; + } + public Builder setService(int index, com.google.protobuf.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + result.service_.set(index, builderForValue.build()); + return this; + } + public Builder addService(com.google.protobuf.DescriptorProtos.ServiceDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.service_.isEmpty()) { + result.service_ = new java.util.ArrayList(); + } + result.service_.add(value); + return this; + } + public Builder addService(com.google.protobuf.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) { + if (result.service_.isEmpty()) { + result.service_ = new java.util.ArrayList(); + } + result.service_.add(builderForValue.build()); + return this; + } + public Builder addAllService( + java.lang.Iterable values) { + if (result.service_.isEmpty()) { + result.service_ = new java.util.ArrayList(); + } + super.addAll(values, result.service_); + return this; + } + public Builder clearService() { + result.service_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + public java.util.List getExtensionList() { + return java.util.Collections.unmodifiableList(result.extension_); + } + public int getExtensionCount() { + return result.getExtensionCount(); + } + public com.google.protobuf.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + return result.getExtension(index); + } + public Builder setExtension(int index, com.google.protobuf.DescriptorProtos.FieldDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.extension_.set(index, value); + return this; + } + public Builder setExtension(int index, com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.extension_.set(index, builderForValue.build()); + return this; + } + public Builder addExtension(com.google.protobuf.DescriptorProtos.FieldDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + result.extension_.add(value); + return this; + } + public Builder addExtension(com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + result.extension_.add(builderForValue.build()); + return this; + } + public Builder addAllExtension( + java.lang.Iterable values) { + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + super.addAll(values, result.extension_); + return this; + } + public Builder clearExtension() { + result.extension_ = java.util.Collections.emptyList(); + return this; + } + + // optional .google.protobuf.FileOptions options = 8; + public boolean hasOptions() { + return result.hasOptions(); + } + public com.google.protobuf.DescriptorProtos.FileOptions getOptions() { + return result.getOptions(); + } + public Builder setOptions(com.google.protobuf.DescriptorProtos.FileOptions value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder setOptions(com.google.protobuf.DescriptorProtos.FileOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.build(); + return this; + } + public Builder mergeOptions(com.google.protobuf.DescriptorProtos.FileOptions value) { + if (result.hasOptions() && + result.options_ != com.google.protobuf.DescriptorProtos.FileOptions.getDefaultInstance()) { + result.options_ = + com.google.protobuf.DescriptorProtos.FileOptions.newBuilder(result.options_).mergeFrom(value).buildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder clearOptions() { + result.hasOptions = false; + result.options_ = com.google.protobuf.DescriptorProtos.FileOptions.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:google.protobuf.FileDescriptorProto) + } + + static { + defaultInstance = new FileDescriptorProto(true); + com.google.protobuf.DescriptorProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + } + + public static final class DescriptorProto extends + com.google.protobuf.GeneratedMessage { + // Use DescriptorProto.newBuilder() to construct. + private DescriptorProto() { + initFields(); + } + private DescriptorProto(boolean noInit) {} + + private static final DescriptorProto defaultInstance; + public static DescriptorProto getDefaultInstance() { + return defaultInstance; + } + + @Override + public DescriptorProto getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_fieldAccessorTable; + } + + public static final class ExtensionRange extends + com.google.protobuf.GeneratedMessage { + // Use ExtensionRange.newBuilder() to construct. + private ExtensionRange() { + initFields(); + } + private ExtensionRange(boolean noInit) {} + + private static final ExtensionRange defaultInstance; + public static ExtensionRange getDefaultInstance() { + return defaultInstance; + } + + @Override + public ExtensionRange getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_DescriptorProto_ExtensionRange_fieldAccessorTable; + } + + // optional int32 start = 1; + public static final int START_FIELD_NUMBER = 1; + private boolean hasStart; + private int start_ = 0; + public boolean hasStart() { return hasStart; } + public int getStart() { return start_; } + + // optional int32 end = 2; + public static final int END_FIELD_NUMBER = 2; + private boolean hasEnd; + private int end_ = 0; + public boolean hasEnd() { return hasEnd; } + public int getEnd() { return end_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasStart()) { + output.writeInt32(1, getStart()); + } + if (hasEnd()) { + output.writeInt32(2, getEnd()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasStart()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, getStart()); + } + if (hasEnd()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getEnd()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange result; + + // Construct using com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange(); + return builder; + } + + @Override + protected com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.getDescriptor(); + } + + @Override + public com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange getDefaultInstanceForType() { + return com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange) { + return mergeFrom((com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange other) { + if (other == com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.getDefaultInstance()) return this; + if (other.hasStart()) { + setStart(other.getStart()); + } + if (other.hasEnd()) { + setEnd(other.getEnd()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setStart(input.readInt32()); + break; + } + case 16: { + setEnd(input.readInt32()); + break; + } + } + } + } + + + // optional int32 start = 1; + public boolean hasStart() { + return result.hasStart(); + } + public int getStart() { + return result.getStart(); + } + public Builder setStart(int value) { + result.hasStart = true; + result.start_ = value; + return this; + } + public Builder clearStart() { + result.hasStart = false; + result.start_ = 0; + return this; + } + + // optional int32 end = 2; + public boolean hasEnd() { + return result.hasEnd(); + } + public int getEnd() { + return result.getEnd(); + } + public Builder setEnd(int value) { + result.hasEnd = true; + result.end_ = value; + return this; + } + public Builder clearEnd() { + result.hasEnd = false; + result.end_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:google.protobuf.DescriptorProto.ExtensionRange) + } + + static { + defaultInstance = new ExtensionRange(true); + com.google.protobuf.DescriptorProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + } + + // optional string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + public static final int FIELD_FIELD_NUMBER = 2; + private java.util.List field_ = + java.util.Collections.emptyList(); + public java.util.List getFieldList() { + return field_; + } + public int getFieldCount() { return field_.size(); } + public com.google.protobuf.DescriptorProtos.FieldDescriptorProto getField(int index) { + return field_.get(index); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + public static final int EXTENSION_FIELD_NUMBER = 6; + private java.util.List extension_ = + java.util.Collections.emptyList(); + public java.util.List getExtensionList() { + return extension_; + } + public int getExtensionCount() { return extension_.size(); } + public com.google.protobuf.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + return extension_.get(index); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + public static final int NESTED_TYPE_FIELD_NUMBER = 3; + private java.util.List nestedType_ = + java.util.Collections.emptyList(); + public java.util.List getNestedTypeList() { + return nestedType_; + } + public int getNestedTypeCount() { return nestedType_.size(); } + public com.google.protobuf.DescriptorProtos.DescriptorProto getNestedType(int index) { + return nestedType_.get(index); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + public static final int ENUM_TYPE_FIELD_NUMBER = 4; + private java.util.List enumType_ = + java.util.Collections.emptyList(); + public java.util.List getEnumTypeList() { + return enumType_; + } + public int getEnumTypeCount() { return enumType_.size(); } + public com.google.protobuf.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + return enumType_.get(index); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + public static final int EXTENSION_RANGE_FIELD_NUMBER = 5; + private java.util.List extensionRange_ = + java.util.Collections.emptyList(); + public java.util.List getExtensionRangeList() { + return extensionRange_; + } + public int getExtensionRangeCount() { return extensionRange_.size(); } + public com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange getExtensionRange(int index) { + return extensionRange_.get(index); + } + + // optional .google.protobuf.MessageOptions options = 7; + public static final int OPTIONS_FIELD_NUMBER = 7; + private boolean hasOptions; + private com.google.protobuf.DescriptorProtos.MessageOptions options_; + public boolean hasOptions() { return hasOptions; } + public com.google.protobuf.DescriptorProtos.MessageOptions getOptions() { return options_; } + + private void initFields() { + options_ = com.google.protobuf.DescriptorProtos.MessageOptions.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getFieldList()) { + if (!element.isInitialized()) return false; + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getExtensionList()) { + if (!element.isInitialized()) return false; + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto element : getNestedTypeList()) { + if (!element.isInitialized()) return false; + } + for (com.google.protobuf.DescriptorProtos.EnumDescriptorProto element : getEnumTypeList()) { + if (!element.isInitialized()) return false; + } + if (hasOptions()) { + if (!getOptions().isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getFieldList()) { + output.writeMessage(2, element); + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto element : getNestedTypeList()) { + output.writeMessage(3, element); + } + for (com.google.protobuf.DescriptorProtos.EnumDescriptorProto element : getEnumTypeList()) { + output.writeMessage(4, element); + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange element : getExtensionRangeList()) { + output.writeMessage(5, element); + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getExtensionList()) { + output.writeMessage(6, element); + } + if (hasOptions()) { + output.writeMessage(7, getOptions()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getFieldList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, element); + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto element : getNestedTypeList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, element); + } + for (com.google.protobuf.DescriptorProtos.EnumDescriptorProto element : getEnumTypeList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, element); + } + for (com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange element : getExtensionRangeList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + for (com.google.protobuf.DescriptorProtos.FieldDescriptorProto element : getExtensionList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + if (hasOptions()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, getOptions()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.protobuf.DescriptorProtos.DescriptorProto parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(com.google.protobuf.DescriptorProtos.DescriptorProto prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private com.google.protobuf.DescriptorProtos.DescriptorProto result; + + // Construct using com.google.protobuf.DescriptorProtos.DescriptorProto.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.google.protobuf.DescriptorProtos.DescriptorProto(); + return builder; + } + + @Override + protected com.google.protobuf.DescriptorProtos.DescriptorProto internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new com.google.protobuf.DescriptorProtos.DescriptorProto(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.google.protobuf.DescriptorProtos.DescriptorProto.getDescriptor(); + } + + @Override + public com.google.protobuf.DescriptorProtos.DescriptorProto getDefaultInstanceForType() { + return com.google.protobuf.DescriptorProtos.DescriptorProto.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public com.google.protobuf.DescriptorProtos.DescriptorProto build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.google.protobuf.DescriptorProtos.DescriptorProto buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public com.google.protobuf.DescriptorProtos.DescriptorProto buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.field_ != java.util.Collections.EMPTY_LIST) { + result.field_ = + java.util.Collections.unmodifiableList(result.field_); + } + if (result.extension_ != java.util.Collections.EMPTY_LIST) { + result.extension_ = + java.util.Collections.unmodifiableList(result.extension_); + } + if (result.nestedType_ != java.util.Collections.EMPTY_LIST) { + result.nestedType_ = + java.util.Collections.unmodifiableList(result.nestedType_); + } + if (result.enumType_ != java.util.Collections.EMPTY_LIST) { + result.enumType_ = + java.util.Collections.unmodifiableList(result.enumType_); + } + if (result.extensionRange_ != java.util.Collections.EMPTY_LIST) { + result.extensionRange_ = + java.util.Collections.unmodifiableList(result.extensionRange_); + } + com.google.protobuf.DescriptorProtos.DescriptorProto returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.protobuf.DescriptorProtos.DescriptorProto) { + return mergeFrom((com.google.protobuf.DescriptorProtos.DescriptorProto)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.protobuf.DescriptorProtos.DescriptorProto other) { + if (other == com.google.protobuf.DescriptorProtos.DescriptorProto.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (!other.field_.isEmpty()) { + if (result.field_.isEmpty()) { + result.field_ = new java.util.ArrayList(); + } + result.field_.addAll(other.field_); + } + if (!other.extension_.isEmpty()) { + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + result.extension_.addAll(other.extension_); + } + if (!other.nestedType_.isEmpty()) { + if (result.nestedType_.isEmpty()) { + result.nestedType_ = new java.util.ArrayList(); + } + result.nestedType_.addAll(other.nestedType_); + } + if (!other.enumType_.isEmpty()) { + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + result.enumType_.addAll(other.enumType_); + } + if (!other.extensionRange_.isEmpty()) { + if (result.extensionRange_.isEmpty()) { + result.extensionRange_ = new java.util.ArrayList(); + } + result.extensionRange_.addAll(other.extensionRange_); + } + if (other.hasOptions()) { + mergeOptions(other.getOptions()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.FieldDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addField(subBuilder.buildPartial()); + break; + } + case 26: { + com.google.protobuf.DescriptorProtos.DescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.DescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addNestedType(subBuilder.buildPartial()); + break; + } + case 34: { + com.google.protobuf.DescriptorProtos.EnumDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.EnumDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addEnumType(subBuilder.buildPartial()); + break; + } + case 42: { + com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.Builder subBuilder = com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addExtensionRange(subBuilder.buildPartial()); + break; + } + case 50: { + com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = com.google.protobuf.DescriptorProtos.FieldDescriptorProto.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addExtension(subBuilder.buildPartial()); + break; + } + case 58: { + com.google.protobuf.DescriptorProtos.MessageOptions.Builder subBuilder = com.google.protobuf.DescriptorProtos.MessageOptions.newBuilder(); + if (hasOptions()) { + subBuilder.mergeFrom(getOptions()); + } + input.readMessage(subBuilder, extensionRegistry); + setOptions(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + public java.util.List getFieldList() { + return java.util.Collections.unmodifiableList(result.field_); + } + public int getFieldCount() { + return result.getFieldCount(); + } + public com.google.protobuf.DescriptorProtos.FieldDescriptorProto getField(int index) { + return result.getField(index); + } + public Builder setField(int index, com.google.protobuf.DescriptorProtos.FieldDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.field_.set(index, value); + return this; + } + public Builder setField(int index, com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.field_.set(index, builderForValue.build()); + return this; + } + public Builder addField(com.google.protobuf.DescriptorProtos.FieldDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.field_.isEmpty()) { + result.field_ = new java.util.ArrayList(); + } + result.field_.add(value); + return this; + } + public Builder addField(com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (result.field_.isEmpty()) { + result.field_ = new java.util.ArrayList(); + } + result.field_.add(builderForValue.build()); + return this; + } + public Builder addAllField( + java.lang.Iterable values) { + if (result.field_.isEmpty()) { + result.field_ = new java.util.ArrayList(); + } + super.addAll(values, result.field_); + return this; + } + public Builder clearField() { + result.field_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + public java.util.List getExtensionList() { + return java.util.Collections.unmodifiableList(result.extension_); + } + public int getExtensionCount() { + return result.getExtensionCount(); + } + public com.google.protobuf.DescriptorProtos.FieldDescriptorProto getExtension(int index) { + return result.getExtension(index); + } + public Builder setExtension(int index, com.google.protobuf.DescriptorProtos.FieldDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.extension_.set(index, value); + return this; + } + public Builder setExtension(int index, com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + result.extension_.set(index, builderForValue.build()); + return this; + } + public Builder addExtension(com.google.protobuf.DescriptorProtos.FieldDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + result.extension_.add(value); + return this; + } + public Builder addExtension(com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) { + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + result.extension_.add(builderForValue.build()); + return this; + } + public Builder addAllExtension( + java.lang.Iterable values) { + if (result.extension_.isEmpty()) { + result.extension_ = new java.util.ArrayList(); + } + super.addAll(values, result.extension_); + return this; + } + public Builder clearExtension() { + result.extension_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + public java.util.List getNestedTypeList() { + return java.util.Collections.unmodifiableList(result.nestedType_); + } + public int getNestedTypeCount() { + return result.getNestedTypeCount(); + } + public com.google.protobuf.DescriptorProtos.DescriptorProto getNestedType(int index) { + return result.getNestedType(index); + } + public Builder setNestedType(int index, com.google.protobuf.DescriptorProtos.DescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.nestedType_.set(index, value); + return this; + } + public Builder setNestedType(int index, com.google.protobuf.DescriptorProtos.DescriptorProto.Builder builderForValue) { + result.nestedType_.set(index, builderForValue.build()); + return this; + } + public Builder addNestedType(com.google.protobuf.DescriptorProtos.DescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.nestedType_.isEmpty()) { + result.nestedType_ = new java.util.ArrayList(); + } + result.nestedType_.add(value); + return this; + } + public Builder addNestedType(com.google.protobuf.DescriptorProtos.DescriptorProto.Builder builderForValue) { + if (result.nestedType_.isEmpty()) { + result.nestedType_ = new java.util.ArrayList(); + } + result.nestedType_.add(builderForValue.build()); + return this; + } + public Builder addAllNestedType( + java.lang.Iterable values) { + if (result.nestedType_.isEmpty()) { + result.nestedType_ = new java.util.ArrayList(); + } + super.addAll(values, result.nestedType_); + return this; + } + public Builder clearNestedType() { + result.nestedType_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + public java.util.List getEnumTypeList() { + return java.util.Collections.unmodifiableList(result.enumType_); + } + public int getEnumTypeCount() { + return result.getEnumTypeCount(); + } + public com.google.protobuf.DescriptorProtos.EnumDescriptorProto getEnumType(int index) { + return result.getEnumType(index); + } + public Builder setEnumType(int index, com.google.protobuf.DescriptorProtos.EnumDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + result.enumType_.set(index, value); + return this; + } + public Builder setEnumType(int index, com.google.protobuf.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + result.enumType_.set(index, builderForValue.build()); + return this; + } + public Builder addEnumType(com.google.protobuf.DescriptorProtos.EnumDescriptorProto value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + result.enumType_.add(value); + return this; + } + public Builder addEnumType(com.google.protobuf.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) { + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + result.enumType_.add(builderForValue.build()); + return this; + } + public Builder addAllEnumType( + java.lang.Iterable values) { + if (result.enumType_.isEmpty()) { + result.enumType_ = new java.util.ArrayList(); + } + super.addAll(values, result.enumType_); + return this; + } + public Builder clearEnumType() { + result.enumType_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + public java.util.List getExtensionRangeList() { + return java.util.Collections.unmodifiableList(result.extensionRange_); + } + public int getExtensionRangeCount() { + return result.getExtensionRangeCount(); + } + public com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange getExtensionRange(int index) { + return result.getExtensionRange(index); + } + public Builder setExtensionRange(int index, com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange value) { + if (value == null) { + throw new NullPointerException(); + } + result.extensionRange_.set(index, value); + return this; + } + public Builder setExtensionRange(int index, com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.Builder builderForValue) { + result.extensionRange_.set(index, builderForValue.build()); + return this; + } + public Builder addExtensionRange(com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.extensionRange_.isEmpty()) { + result.extensionRange_ = new java.util.ArrayList(); + } + result.extensionRange_.add(value); + return this; + } + public Builder addExtensionRange(com.google.protobuf.DescriptorProtos.DescriptorProto.ExtensionRange.Builder builderForValue) { + if (result.extensionRange_.isEmpty()) { + result.extensionRange_ = new java.util.ArrayList(); + } + result.extensionRange_.add(builderForValue.build()); + return this; + } + public Builder addAllExtensionRange( + java.lang.Iterable values) { + if (result.extensionRange_.isEmpty()) { + result.extensionRange_ = new java.util.ArrayList(); + } + super.addAll(values, result.extensionRange_); + return this; + } + public Builder clearExtensionRange() { + result.extensionRange_ = java.util.Collections.emptyList(); + return this; + } + + // optional .google.protobuf.MessageOptions options = 7; + public boolean hasOptions() { + return result.hasOptions(); + } + public com.google.protobuf.DescriptorProtos.MessageOptions getOptions() { + return result.getOptions(); + } + public Builder setOptions(com.google.protobuf.DescriptorProtos.MessageOptions value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasOptions = true; + result.options_ = value; + return this; + } + public Builder setOptions(com.google.protobuf.DescriptorProtos.MessageOptions.Builder builderForValue) { + result.hasOptions = true; + result.options_ = builderForValue.build(); + return this; + } + public Builder mergeOptions(com.google.protobuf.DescriptorProtos.MessageOptions value) { + if (result.hasOptions() && + result.options_ != com.google.protobuf.DescriptorProtos.MessageOptions.getDefaultInstance()) { + result.options_ = + com.google.protobuf.DescriptorProtos.MessageOptions.newBuilder(result.options_).mergeFrom(value).buildPartial(); + } else { + result.options_ = value; + } + result.hasOptions = true; + return this; + } + public Builder clearOptions() { + result.hasOptions = false; + result.options_ = com.google.protobuf.DescriptorProtos.MessageOptions.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:google.protobuf.DescriptorProto) + } + + static { + defaultInstance = new DescriptorProto(true); + com.google.protobuf.DescriptorProtos.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + } + + public static final class FieldDescriptorProto extends + com.google.protobuf.GeneratedMessage { + // Use FieldDescriptorProto.newBuilder() to construct. + private FieldDescriptorProto() { + initFields(); + } + private FieldDescriptorProto(boolean noInit) {} + + private static final FieldDescriptorProto defaultInstance; + public static FieldDescriptorProto getDefaultInstance() { + return defaultInstance; + } + + @Override + public FieldDescriptorProto getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_FieldDescriptorProto_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.protobuf.DescriptorProtos.internal_static_google_protobuf_FieldDescriptorProto_fieldAccessorTable; + } + + public enum Type + implements com.google.protobuf.ProtocolMessageEnum { + TYPE_DOUBLE(0, 1), + TYPE_FLOAT(1, 2), + TYPE_INT64(2, 3), + TYPE_UINT64(3, 4), + TYPE_INT32(4, 5), + TYPE_FIXED64(5, 6), + TYPE_FIXED32(6, 7), + TYPE_BOOL(7, 8), + TYPE_STRING(8, 9), + TYPE_GROUP(9, 10), + TYPE_MESSAGE(10, 11), + TYPE_BYTES(11, 12), + TYPE_UINT32(12, 13), + TYPE_ENUM(13, 14), + TYPE_SFIXED32(14, 15), + TYPE_SFIXED64(15, 16), + TYPE_SINT32(16, 17), + TYPE_SINT64(17, 18), + ; + + + @Override + public final int getNumber() { return value; } + + public static Type valueOf(int value) { + switch (value) { + case 1: return TYPE_DOUBLE; + case 2: return TYPE_FLOAT; + case 3: return TYPE_INT64; + case 4: return TYPE_UINT64; + case 5: return TYPE_INT32; + case 6: return TYPE_FIXED64; + case 7: return TYPE_FIXED32; + case 8: return TYPE_BOOL; + case 9: return TYPE_STRING; + case 10: return TYPE_GROUP; + case 11: return TYPE_MESSAGE; + case 12: return TYPE_BYTES; + case 13: return TYPE_UINT32; + case 14: return TYPE_ENUM; + case 15: return TYPE_SFIXED32; + case 16: return TYPE_SFIXED64; + case 17: return TYPE_SINT32; + case 18: return TYPE_SINT64; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static com.google.protobuf.Internal.EnumLiteMap + internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + @Override + public Type findValueByNumber(int number) { + return Type.valueOf(number) + ; } + }; + + @Override + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + @Override + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return com.google.protobuf.DescriptorProtos.FieldDescriptorProto.getDescriptor().getEnumTypes().get(0); + } + + private static final Type[] VALUES = { + TYPE_DOUBLE, TYPE_FLOAT, TYPE_INT64, TYPE_UINT64, TYPE_INT32, TYPE_FIXED64, TYPE_FIXED32, TYPE_BOOL, TYPE_STRING, TYPE_GROUP, TYPE_MESSAGE, TYPE_BYTES, TYPE_UINT32, TYPE_ENUM, TYPE_SFIXED32, TYPE_SFIXED64, TYPE_SINT32, TYPE_SINT64, + }; + public static Type valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + private final int index; + private final int value; + private Type(int index, int value) { + this.index = index; + this.value = value; + } + + static { + com.google.protobuf.DescriptorProtos.getDescriptor(); + } + + // @@protoc_insertion_point(enum_scope:google.protobuf.FieldDescriptorProto.Type) + } + + public enum Label + implements com.google.protobuf.ProtocolMessageEnum { + LABEL_OPTIONAL(0, 1), + LABEL_REQUIRED(1, 2), + LABEL_REPEATED(2, 3), + ; + + + @Override + public final int getNumber() { return value; } + + public static Label valueOf(int value) { + switch (value) { + case 1: return LABEL_OPTIONAL; + case 2: return LABEL_REQUIRED; + case 3: return LABEL_REPEATED; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap

+     *   for all i in [0, file.getMessageTypeCount()):
+     *     file.getMessageType(i).getIndex() == i
+     * 
+ * Similarly, for a {@link Descriptor} {@code messageType}: + *
+     *   for all i in [0, messageType.getNestedTypeCount()):
+     *     messageType.getNestedType(i).getIndex() == i
+     * 
+ */ + public int getIndex() { return index; } + + /** Convert the descriptor to its protocol message representation. */ + @Override + public DescriptorProto toProto() { return proto; } + + /** Get the type's unqualified name. */ + @Override + public String getName() { return proto.getName(); } + + /** + * Get the type's fully-qualified name, within the proto language's + * namespace. This differs from the Java name. For example, given this + * {@code .proto}: + *
+     *   package foo.bar;
+     *   option java_package = "com.example.protos"
+     *   message Baz {}
+     * 
+ * {@code Baz}'s full name is "foo.bar.Baz". + */ + @Override + public String getFullName() { return fullName; } + + /** Get the {@link FileDescriptor} containing this descriptor. */ + @Override + public FileDescriptor getFile() { return file; } + + /** If this is a nested type, get the outer descriptor, otherwise null. */ + public Descriptor getContainingType() { return containingType; } + + /** Get the {@code MessageOptions}, defined in {@code descriptor.proto}. */ + public MessageOptions getOptions() { return proto.getOptions(); } + + /** Get a list of this message type's fields. */ + public List getFields() { + return Collections.unmodifiableList(Arrays.asList(fields)); + } + + /** Get a list of this message type's extensions. */ + public List getExtensions() { + return Collections.unmodifiableList(Arrays.asList(extensions)); + } + + /** Get a list of message types nested within this one. */ + public List getNestedTypes() { + return Collections.unmodifiableList(Arrays.asList(nestedTypes)); + } + + /** Get a list of enum types nested within this one. */ + public List getEnumTypes() { + return Collections.unmodifiableList(Arrays.asList(enumTypes)); + } + + /** Determines if the given field number is an extension. */ + public boolean isExtensionNumber(final int number) { + for (final DescriptorProto.ExtensionRange range : + proto.getExtensionRangeList()) { + if (range.getStart() <= number && number < range.getEnd()) { + return true; + } + } + return false; + } + + /** + * Finds a field by name. + * @param name The unqualified name of the field (e.g. "foo"). + * @return The field's descriptor, or {@code null} if not found. + */ + public FieldDescriptor findFieldByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); + if (result != null && result instanceof FieldDescriptor) { + return (FieldDescriptor)result; + } else { + return null; + } + } + + /** + * Finds a field by field number. + * @param number The field number within this message type. + * @return The field's descriptor, or {@code null} if not found. + */ + public FieldDescriptor findFieldByNumber(final int number) { + return file.pool.fieldsByNumber.get( + new DescriptorPool.DescriptorIntPair(this, number)); + } + + /** + * Finds a nested message type by name. + * @param name The unqualified name of the nested type (e.g. "Foo"). + * @return The types's descriptor, or {@code null} if not found. + */ + public Descriptor findNestedTypeByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); + if (result != null && result instanceof Descriptor) { + return (Descriptor)result; + } else { + return null; + } + } + + /** + * Finds a nested enum type by name. + * @param name The unqualified name of the nested type (e.g. "Foo"). + * @return The types's descriptor, or {@code null} if not found. + */ + public EnumDescriptor findEnumTypeByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); + if (result != null && result instanceof EnumDescriptor) { + return (EnumDescriptor)result; + } else { + return null; + } + } + + private final int index; + private DescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + private final Descriptor containingType; + private final Descriptor[] nestedTypes; + private final EnumDescriptor[] enumTypes; + private final FieldDescriptor[] fields; + private final FieldDescriptor[] extensions; + + private Descriptor(final DescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) + throws DescriptorValidationException { + this.index = index; + this.proto = proto; + fullName = computeFullName(file, parent, proto.getName()); + this.file = file; + containingType = parent; + + nestedTypes = new Descriptor[proto.getNestedTypeCount()]; + for (int i = 0; i < proto.getNestedTypeCount(); i++) { + nestedTypes[i] = new Descriptor( + proto.getNestedType(i), file, this, i); + } + + enumTypes = new EnumDescriptor[proto.getEnumTypeCount()]; + for (int i = 0; i < proto.getEnumTypeCount(); i++) { + enumTypes[i] = new EnumDescriptor( + proto.getEnumType(i), file, this, i); + } + + fields = new FieldDescriptor[proto.getFieldCount()]; + for (int i = 0; i < proto.getFieldCount(); i++) { + fields[i] = new FieldDescriptor( + proto.getField(i), file, this, i, false); + } + + extensions = new FieldDescriptor[proto.getExtensionCount()]; + for (int i = 0; i < proto.getExtensionCount(); i++) { + extensions[i] = new FieldDescriptor( + proto.getExtension(i), file, this, i, true); + } + + file.pool.addSymbol(this); + } + + /** Look up and cross-link all field types, etc. */ + private void crossLink() throws DescriptorValidationException { + for (final Descriptor nestedType : nestedTypes) { + nestedType.crossLink(); + } + + for (final FieldDescriptor field : fields) { + field.crossLink(); + } + + for (final FieldDescriptor extension : extensions) { + extension.crossLink(); + } + } + + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final DescriptorProto proto) { + this.proto = proto; + + for (int i = 0; i < nestedTypes.length; i++) { + nestedTypes[i].setProto(proto.getNestedType(i)); + } + + for (int i = 0; i < enumTypes.length; i++) { + enumTypes[i].setProto(proto.getEnumType(i)); + } + + for (int i = 0; i < fields.length; i++) { + fields[i].setProto(proto.getField(i)); + } + + for (int i = 0; i < extensions.length; i++) { + extensions[i].setProto(proto.getExtension(i)); + } + } + } + + // ================================================================= + + /** Describes a field of a message type. */ + public static final class FieldDescriptor + implements GenericDescriptor, Comparable, + FieldSet.FieldDescriptorLite { + /** + * Get the index of this descriptor within its parent. + * @see Descriptor#getIndex() + */ + public int getIndex() { return index; } + + /** Convert the descriptor to its protocol message representation. */ + @Override + public FieldDescriptorProto toProto() { return proto; } + + /** Get the field's unqualified name. */ + @Override + public String getName() { return proto.getName(); } + + /** Get the field's number. */ + @Override + public int getNumber() { return proto.getNumber(); } + + /** + * Get the field's fully-qualified name. + * @see Descriptor#getFullName() + */ + @Override + public String getFullName() { return fullName; } + + /** + * Get the field's java type. This is just for convenience. Every + * {@code FieldDescriptorProto.Type} maps to exactly one Java type. + */ + public JavaType getJavaType() { return type.getJavaType(); } + + /** For internal use only. */ + @Override + public WireFormat.JavaType getLiteJavaType() { + return getLiteType().getJavaType(); + } + + /** Get the {@code FileDescriptor} containing this descriptor. */ + @Override + public FileDescriptor getFile() { return file; } + + /** Get the field's declared type. */ + public Type getType() { return type; } + + /** For internal use only. */ + @Override + public WireFormat.FieldType getLiteType() { + return table[type.ordinal()]; + } + // I'm pretty sure values() constructs a new array every time, since there + // is nothing stopping the caller from mutating the array. Therefore we + // make a static copy here. + private static final WireFormat.FieldType[] table = + WireFormat.FieldType.values(); + + /** Is this field declared required? */ + public boolean isRequired() { + return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED; + } + + /** Is this field declared optional? */ + public boolean isOptional() { + return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL; + } + + /** Is this field declared repeated? */ + @Override + public boolean isRepeated() { + return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED; + } + + /** Does this field have the {@code [packed = true]} option? */ + @Override + public boolean isPacked() { + return getOptions().getPacked(); + } + + /** Can this field be packed? i.e. is it a repeated primitive field? */ + public boolean isPackable() { + return isRepeated() && getLiteType().isPackable(); + } + + /** Returns true if the field had an explicitly-defined default value. */ + public boolean hasDefaultValue() { return proto.hasDefaultValue(); } + + /** + * Returns the field's default value. Valid for all types except for + * messages and groups. For all other types, the object returned is of + * the same class that would returned by Message.getField(this). + */ + public Object getDefaultValue() { + if (getJavaType() == JavaType.MESSAGE) { + throw new UnsupportedOperationException( + "FieldDescriptor.getDefaultValue() called on an embedded message " + + "field."); + } + return defaultValue; + } + + /** Get the {@code FieldOptions}, defined in {@code descriptor.proto}. */ + public FieldOptions getOptions() { return proto.getOptions(); } + + /** Is this field an extension? */ + public boolean isExtension() { return proto.hasExtendee(); } + + /** + * Get the field's containing type. For extensions, this is the type being + * extended, not the location where the extension was defined. See + * {@link #getExtensionScope()}. + */ + public Descriptor getContainingType() { return containingType; } + + /** + * For extensions defined nested within message types, gets the outer + * type. Not valid for non-extension fields. For example, consider + * this {@code .proto} file: + *
+     *   message Foo {
+     *     extensions 1000 to max;
+     *   }
+     *   extend Foo {
+     *     optional int32 baz = 1234;
+     *   }
+     *   message Bar {
+     *     extend Foo {
+     *       optional int32 qux = 4321;
+     *     }
+     *   }
+     * 
+ * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}. + * However, {@code baz}'s extension scope is {@code null} while + * {@code qux}'s extension scope is {@code Bar}. + */ + public Descriptor getExtensionScope() { + if (!isExtension()) { + throw new UnsupportedOperationException( + "This field is not an extension."); + } + return extensionScope; + } + + /** For embedded message and group fields, gets the field's type. */ + public Descriptor getMessageType() { + if (getJavaType() != JavaType.MESSAGE) { + throw new UnsupportedOperationException( + "This field is not of message type."); + } + return messageType; + } + + /** For enum fields, gets the field's type. */ + @Override + public EnumDescriptor getEnumType() { + if (getJavaType() != JavaType.ENUM) { + throw new UnsupportedOperationException( + "This field is not of enum type."); + } + return enumType; + } + + /** + * Compare with another {@code FieldDescriptor}. This orders fields in + * "canonical" order, which simply means ascending order by field number. + * {@code other} must be a field of the same type -- i.e. + * {@code getContainingType()} must return the same {@code Descriptor} for + * both fields. + * + * @return negative, zero, or positive if {@code this} is less than, + * equal to, or greater than {@code other}, respectively. + */ + @Override + public int compareTo(final FieldDescriptor other) { + if (other.containingType != containingType) { + throw new IllegalArgumentException( + "FieldDescriptors can only be compared to other FieldDescriptors " + + "for fields of the same message type."); + } + return getNumber() - other.getNumber(); + } + + private final int index; + + private FieldDescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + private final Descriptor extensionScope; + + // Possibly initialized during cross-linking. + private Type type; + private Descriptor containingType; + private Descriptor messageType; + private EnumDescriptor enumType; + private Object defaultValue; + + public enum Type { + DOUBLE (JavaType.DOUBLE ), + FLOAT (JavaType.FLOAT ), + INT64 (JavaType.LONG ), + UINT64 (JavaType.LONG ), + INT32 (JavaType.INT ), + FIXED64 (JavaType.LONG ), + FIXED32 (JavaType.INT ), + BOOL (JavaType.BOOLEAN ), + STRING (JavaType.STRING ), + GROUP (JavaType.MESSAGE ), + MESSAGE (JavaType.MESSAGE ), + BYTES (JavaType.BYTE_STRING), + UINT32 (JavaType.INT ), + ENUM (JavaType.ENUM ), + SFIXED32(JavaType.INT ), + SFIXED64(JavaType.LONG ), + SINT32 (JavaType.INT ), + SINT64 (JavaType.LONG ); + + Type(final JavaType javaType) { + this.javaType = javaType; + } + + private JavaType javaType; + + public FieldDescriptorProto.Type toProto() { + return FieldDescriptorProto.Type.valueOf(ordinal() + 1); + } + public JavaType getJavaType() { return javaType; } + + public static Type valueOf(final FieldDescriptorProto.Type type) { + return values()[type.getNumber() - 1]; + } + } + + static { + // Refuse to init if someone added a new declared type. + if (Type.values().length != FieldDescriptorProto.Type.values().length) { + throw new RuntimeException( + "descriptor.proto has a new declared type but Desrciptors.java " + + "wasn't updated."); + } + } + + public enum JavaType { + INT(0), + LONG(0L), + FLOAT(0F), + DOUBLE(0D), + BOOLEAN(false), + STRING(""), + BYTE_STRING(ByteString.EMPTY), + ENUM(null), + MESSAGE(null); + + JavaType(final Object defaultDefault) { + this.defaultDefault = defaultDefault; + } + + /** + * The default default value for fields of this type, if it's a primitive + * type. This is meant for use inside this file only, hence is private. + */ + private final Object defaultDefault; + } + + private FieldDescriptor(final FieldDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index, + final boolean isExtension) + throws DescriptorValidationException { + this.index = index; + this.proto = proto; + fullName = computeFullName(file, parent, proto.getName()); + this.file = file; + + if (proto.hasType()) { + type = Type.valueOf(proto.getType()); + } + + if (getNumber() <= 0) { + throw new DescriptorValidationException(this, + "Field numbers must be positive integers."); + } + + // Only repeated primitive fields may be packed. + if (proto.getOptions().getPacked() && !isPackable()) { + throw new DescriptorValidationException(this, + "[packed = true] can only be specified for repeated primitive " + + "fields."); + } + + if (isExtension) { + if (!proto.hasExtendee()) { + throw new DescriptorValidationException(this, + "FieldDescriptorProto.extendee not set for extension field."); + } + containingType = null; // Will be filled in when cross-linking + if (parent != null) { + extensionScope = parent; + } else { + extensionScope = null; + } + } else { + if (proto.hasExtendee()) { + throw new DescriptorValidationException(this, + "FieldDescriptorProto.extendee set for non-extension field."); + } + containingType = parent; + extensionScope = null; + } + + file.pool.addSymbol(this); + } + + /** Look up and cross-link all field types, etc. */ + private void crossLink() throws DescriptorValidationException { + if (proto.hasExtendee()) { + final GenericDescriptor extendee = + file.pool.lookupSymbol(proto.getExtendee(), this); + if (!(extendee instanceof Descriptor)) { + throw new DescriptorValidationException(this, + '\"' + proto.getExtendee() + "\" is not a message type."); + } + containingType = (Descriptor)extendee; + + if (!getContainingType().isExtensionNumber(getNumber())) { + throw new DescriptorValidationException(this, + '\"' + getContainingType().getFullName() + + "\" does not declare " + getNumber() + + " as an extension number."); + } + } + + if (proto.hasTypeName()) { + final GenericDescriptor typeDescriptor = + file.pool.lookupSymbol(proto.getTypeName(), this); + + if (!proto.hasType()) { + // Choose field type based on symbol. + if (typeDescriptor instanceof Descriptor) { + type = Type.MESSAGE; + } else if (typeDescriptor instanceof EnumDescriptor) { + type = Type.ENUM; + } else { + throw new DescriptorValidationException(this, + '\"' + proto.getTypeName() + "\" is not a type."); + } + } + + if (getJavaType() == JavaType.MESSAGE) { + if (!(typeDescriptor instanceof Descriptor)) { + throw new DescriptorValidationException(this, + '\"' + proto.getTypeName() + "\" is not a message type."); + } + messageType = (Descriptor)typeDescriptor; + + if (proto.hasDefaultValue()) { + throw new DescriptorValidationException(this, + "Messages can't have default values."); + } + } else if (getJavaType() == JavaType.ENUM) { + if (!(typeDescriptor instanceof EnumDescriptor)) { + throw new DescriptorValidationException(this, + '\"' + proto.getTypeName() + "\" is not an enum type."); + } + enumType = (EnumDescriptor)typeDescriptor; + } else { + throw new DescriptorValidationException(this, + "Field with primitive type has type_name."); + } + } else { + if (getJavaType() == JavaType.MESSAGE || + getJavaType() == JavaType.ENUM) { + throw new DescriptorValidationException(this, + "Field with message or enum type missing type_name."); + } + } + + // We don't attempt to parse the default value until here because for + // enums we need the enum type's descriptor. + if (proto.hasDefaultValue()) { + if (isRepeated()) { + throw new DescriptorValidationException(this, + "Repeated fields cannot have default values."); + } + + try { + switch (getType()) { + case INT32: + case SINT32: + case SFIXED32: + defaultValue = TextFormat.parseInt32(proto.getDefaultValue()); + break; + case UINT32: + case FIXED32: + defaultValue = TextFormat.parseUInt32(proto.getDefaultValue()); + break; + case INT64: + case SINT64: + case SFIXED64: + defaultValue = TextFormat.parseInt64(proto.getDefaultValue()); + break; + case UINT64: + case FIXED64: + defaultValue = TextFormat.parseUInt64(proto.getDefaultValue()); + break; + case FLOAT: + if (proto.getDefaultValue().equals("inf")) { + defaultValue = Float.POSITIVE_INFINITY; + } else if (proto.getDefaultValue().equals("-inf")) { + defaultValue = Float.NEGATIVE_INFINITY; + } else if (proto.getDefaultValue().equals("nan")) { + defaultValue = Float.NaN; + } else { + defaultValue = Float.valueOf(proto.getDefaultValue()); + } + break; + case DOUBLE: + if (proto.getDefaultValue().equals("inf")) { + defaultValue = Double.POSITIVE_INFINITY; + } else if (proto.getDefaultValue().equals("-inf")) { + defaultValue = Double.NEGATIVE_INFINITY; + } else if (proto.getDefaultValue().equals("nan")) { + defaultValue = Double.NaN; + } else { + defaultValue = Double.valueOf(proto.getDefaultValue()); + } + break; + case BOOL: + defaultValue = Boolean.valueOf(proto.getDefaultValue()); + break; + case STRING: + defaultValue = proto.getDefaultValue(); + break; + case BYTES: + try { + defaultValue = + TextFormat.unescapeBytes(proto.getDefaultValue()); + } catch (TextFormat.InvalidEscapeSequenceException e) { + throw new DescriptorValidationException(this, + "Couldn't parse default value: " + e.getMessage(), e); + } + break; + case ENUM: + defaultValue = enumType.findValueByName(proto.getDefaultValue()); + if (defaultValue == null) { + throw new DescriptorValidationException(this, + "Unknown enum default value: \"" + + proto.getDefaultValue() + '\"'); + } + break; + case MESSAGE: + case GROUP: + throw new DescriptorValidationException(this, + "Message type had default value."); + } + } catch (NumberFormatException e) { + throw new DescriptorValidationException(this, + "Could not parse default value: \"" + + proto.getDefaultValue() + '\"', e); + } + } else { + // Determine the default default for this field. + if (isRepeated()) { + defaultValue = Collections.emptyList(); + } else { + switch (getJavaType()) { + case ENUM: + // We guarantee elsewhere that an enum type always has at least + // one possible value. + defaultValue = enumType.getValues().get(0); + break; + case MESSAGE: + defaultValue = null; + break; + default: + defaultValue = getJavaType().defaultDefault; + break; + } + } + } + + if (!isExtension()) { + file.pool.addFieldByNumber(this); + } + + if (containingType != null && + containingType.getOptions().getMessageSetWireFormat()) { + if (isExtension()) { + if (!isOptional() || getType() != Type.MESSAGE) { + throw new DescriptorValidationException(this, + "Extensions of MessageSets must be optional messages."); + } + } else { + throw new DescriptorValidationException(this, + "MessageSets cannot have fields, only extensions."); + } + } + } + + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final FieldDescriptorProto proto) { + this.proto = proto; + } + + /** + * For internal use only. This is to satisfy the FieldDescriptorLite + * interface. + */ + @Override + public MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from) { + // FieldDescriptors are only used with non-lite messages so we can just + // down-cast and call mergeFrom directly. + return ((Message.Builder) to).mergeFrom((Message) from); + } + } + + // ================================================================= + + /** Describes an enum type. */ + public static final class EnumDescriptor + implements GenericDescriptor, Internal.EnumLiteMap { + /** + * Get the index of this descriptor within its parent. + * @see Descriptor#getIndex() + */ + public int getIndex() { return index; } + + /** Convert the descriptor to its protocol message representation. */ + @Override + public EnumDescriptorProto toProto() { return proto; } + + /** Get the type's unqualified name. */ + @Override + public String getName() { return proto.getName(); } + + /** + * Get the type's fully-qualified name. + * @see Descriptor#getFullName() + */ + @Override + public String getFullName() { return fullName; } + + /** Get the {@link FileDescriptor} containing this descriptor. */ + @Override + public FileDescriptor getFile() { return file; } + + /** If this is a nested type, get the outer descriptor, otherwise null. */ + public Descriptor getContainingType() { return containingType; } + + /** Get the {@code EnumOptions}, defined in {@code descriptor.proto}. */ + public EnumOptions getOptions() { return proto.getOptions(); } + + /** Get a list of defined values for this enum. */ + public List getValues() { + return Collections.unmodifiableList(Arrays.asList(values)); + } + + /** + * Find an enum value by name. + * @param name The unqualified name of the value (e.g. "FOO"). + * @return the value's decsriptor, or {@code null} if not found. + */ + public EnumValueDescriptor findValueByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); + if (result != null && result instanceof EnumValueDescriptor) { + return (EnumValueDescriptor)result; + } else { + return null; + } + } + + /** + * Find an enum value by number. If multiple enum values have the same + * number, this returns the first defined value with that number. + * @param number The value's number. + * @return the value's decsriptor, or {@code null} if not found. + */ + @Override + public EnumValueDescriptor findValueByNumber(final int number) { + return file.pool.enumValuesByNumber.get( + new DescriptorPool.DescriptorIntPair(this, number)); + } + + private final int index; + private EnumDescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + private final Descriptor containingType; + private EnumValueDescriptor[] values; + + private EnumDescriptor(final EnumDescriptorProto proto, + final FileDescriptor file, + final Descriptor parent, + final int index) + throws DescriptorValidationException { + this.index = index; + this.proto = proto; + fullName = computeFullName(file, parent, proto.getName()); + this.file = file; + containingType = parent; + + if (proto.getValueCount() == 0) { + // We cannot allow enums with no values because this would mean there + // would be no valid default value for fields of this type. + throw new DescriptorValidationException(this, + "Enums must contain at least one value."); + } + + values = new EnumValueDescriptor[proto.getValueCount()]; + for (int i = 0; i < proto.getValueCount(); i++) { + values[i] = new EnumValueDescriptor( + proto.getValue(i), file, this, i); + } + + file.pool.addSymbol(this); + } + + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final EnumDescriptorProto proto) { + this.proto = proto; + + for (int i = 0; i < values.length; i++) { + values[i].setProto(proto.getValue(i)); + } + } + } + + // ================================================================= + + /** + * Describes one value within an enum type. Note that multiple defined + * values may have the same number. In generated Java code, all values + * with the same number after the first become aliases of the first. + * However, they still have independent EnumValueDescriptors. + */ + public static final class EnumValueDescriptor + implements GenericDescriptor, Internal.EnumLite { + /** + * Get the index of this descriptor within its parent. + * @see Descriptor#getIndex() + */ + public int getIndex() { return index; } + + /** Convert the descriptor to its protocol message representation. */ + @Override + public EnumValueDescriptorProto toProto() { return proto; } + + /** Get the value's unqualified name. */ + @Override + public String getName() { return proto.getName(); } + + /** Get the value's number. */ + @Override + public int getNumber() { return proto.getNumber(); } + + /** + * Get the value's fully-qualified name. + * @see Descriptor#getFullName() + */ + @Override + public String getFullName() { return fullName; } + + /** Get the {@link FileDescriptor} containing this descriptor. */ + @Override + public FileDescriptor getFile() { return file; } + + /** Get the value's enum type. */ + public EnumDescriptor getType() { return type; } + + /** + * Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}. + */ + public EnumValueOptions getOptions() { return proto.getOptions(); } + + private final int index; + private EnumValueDescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + private final EnumDescriptor type; + + private EnumValueDescriptor(final EnumValueDescriptorProto proto, + final FileDescriptor file, + final EnumDescriptor parent, + final int index) + throws DescriptorValidationException { + this.index = index; + this.proto = proto; + this.file = file; + type = parent; + + fullName = parent.getFullName() + '.' + proto.getName(); + + file.pool.addSymbol(this); + file.pool.addEnumValueByNumber(this); + } + + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final EnumValueDescriptorProto proto) { + this.proto = proto; + } + } + + // ================================================================= + + /** Describes a service type. */ + public static final class ServiceDescriptor implements GenericDescriptor { + /** + * Get the index of this descriptor within its parent. + * * @see Descriptors.Descriptor#getIndex() + */ + public int getIndex() { return index; } + + /** Convert the descriptor to its protocol message representation. */ + @Override + public ServiceDescriptorProto toProto() { return proto; } + + /** Get the type's unqualified name. */ + @Override + public String getName() { return proto.getName(); } + + /** + * Get the type's fully-qualified name. + * @see Descriptor#getFullName() + */ + @Override + public String getFullName() { return fullName; } + + /** Get the {@link FileDescriptor} containing this descriptor. */ + @Override + public FileDescriptor getFile() { return file; } + + /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */ + public ServiceOptions getOptions() { return proto.getOptions(); } + + /** Get a list of methods for this service. */ + public List getMethods() { + return Collections.unmodifiableList(Arrays.asList(methods)); + } + + /** + * Find a method by name. + * @param name The unqualified name of the method (e.g. "Foo"). + * @return the method's decsriptor, or {@code null} if not found. + */ + public MethodDescriptor findMethodByName(final String name) { + final GenericDescriptor result = + file.pool.findSymbol(fullName + '.' + name); + if (result != null && result instanceof MethodDescriptor) { + return (MethodDescriptor)result; + } else { + return null; + } + } + + private final int index; + private ServiceDescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + private MethodDescriptor[] methods; + + private ServiceDescriptor(final ServiceDescriptorProto proto, + final FileDescriptor file, + final int index) + throws DescriptorValidationException { + this.index = index; + this.proto = proto; + fullName = computeFullName(file, null, proto.getName()); + this.file = file; + + methods = new MethodDescriptor[proto.getMethodCount()]; + for (int i = 0; i < proto.getMethodCount(); i++) { + methods[i] = new MethodDescriptor( + proto.getMethod(i), file, this, i); + } + + file.pool.addSymbol(this); + } + + private void crossLink() throws DescriptorValidationException { + for (final MethodDescriptor method : methods) { + method.crossLink(); + } + } + + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final ServiceDescriptorProto proto) { + this.proto = proto; + + for (int i = 0; i < methods.length; i++) { + methods[i].setProto(proto.getMethod(i)); + } + } + } + + // ================================================================= + + /** + * Describes one method within a service type. + */ + public static final class MethodDescriptor implements GenericDescriptor { + /** + * Get the index of this descriptor within its parent. + * * @see Descriptors.Descriptor#getIndex() + */ + public int getIndex() { return index; } + + /** Convert the descriptor to its protocol message representation. */ + @Override + public MethodDescriptorProto toProto() { return proto; } + + /** Get the method's unqualified name. */ + @Override + public String getName() { return proto.getName(); } + + /** + * Get the method's fully-qualified name. + * @see Descriptor#getFullName() + */ + @Override + public String getFullName() { return fullName; } + + /** Get the {@link FileDescriptor} containing this descriptor. */ + @Override + public FileDescriptor getFile() { return file; } + + /** Get the method's service type. */ + public ServiceDescriptor getService() { return service; } + + /** Get the method's input type. */ + public Descriptor getInputType() { return inputType; } + + /** Get the method's output type. */ + public Descriptor getOutputType() { return outputType; } + + /** + * Get the {@code MethodOptions}, defined in {@code descriptor.proto}. + */ + public MethodOptions getOptions() { return proto.getOptions(); } + + private final int index; + private MethodDescriptorProto proto; + private final String fullName; + private final FileDescriptor file; + private final ServiceDescriptor service; + + // Initialized during cross-linking. + private Descriptor inputType; + private Descriptor outputType; + + private MethodDescriptor(final MethodDescriptorProto proto, + final FileDescriptor file, + final ServiceDescriptor parent, + final int index) + throws DescriptorValidationException { + this.index = index; + this.proto = proto; + this.file = file; + service = parent; + + fullName = parent.getFullName() + '.' + proto.getName(); + + file.pool.addSymbol(this); + } + + private void crossLink() throws DescriptorValidationException { + final GenericDescriptor input = + file.pool.lookupSymbol(proto.getInputType(), this); + if (!(input instanceof Descriptor)) { + throw new DescriptorValidationException(this, + '\"' + proto.getInputType() + "\" is not a message type."); + } + inputType = (Descriptor)input; + + final GenericDescriptor output = + file.pool.lookupSymbol(proto.getOutputType(), this); + if (!(output instanceof Descriptor)) { + throw new DescriptorValidationException(this, + '\"' + proto.getOutputType() + "\" is not a message type."); + } + outputType = (Descriptor)output; + } + + /** See {@link FileDescriptor#setProto}. */ + private void setProto(final MethodDescriptorProto proto) { + this.proto = proto; + } + } + + // ================================================================= + + private static String computeFullName(final FileDescriptor file, + final Descriptor parent, + final String name) { + if (parent != null) { + return parent.getFullName() + '.' + name; + } else if (file.getPackage().length() > 0) { + return file.getPackage() + '.' + name; + } else { + return name; + } + } + + // ================================================================= + + /** + * All descriptors except {@code FileDescriptor} implement this to make + * {@code DescriptorPool}'s life easier. + */ + private interface GenericDescriptor { + Message toProto(); + String getName(); + String getFullName(); + FileDescriptor getFile(); + } + + /** + * Thrown when building descriptors fails because the source DescriptorProtos + * are not valid. + */ + public static class DescriptorValidationException extends Exception { + private static final long serialVersionUID = 5750205775490483148L; + + /** Gets the full name of the descriptor where the error occurred. */ + public String getProblemSymbolName() { return name; } + + /** + * Gets the the protocol message representation of the invalid descriptor. + */ + public Message getProblemProto() { return proto; } + + /** + * Gets a human-readable description of the error. + */ + public String getDescription() { return description; } + + private final String name; + private final Message proto; + private final String description; + + private DescriptorValidationException( + final GenericDescriptor problemDescriptor, + final String description) { + super(problemDescriptor.getFullName() + ": " + description); + + // Note that problemDescriptor may be partially uninitialized, so we + // don't want to expose it directly to the user. So, we only provide + // the name and the original proto. + name = problemDescriptor.getFullName(); + proto = problemDescriptor.toProto(); + this.description = description; + } + + private DescriptorValidationException( + final GenericDescriptor problemDescriptor, + final String description, + final Throwable cause) { + this(problemDescriptor, description); + initCause(cause); + } + + private DescriptorValidationException( + final FileDescriptor problemDescriptor, + final String description) { + super(problemDescriptor.getName() + ": " + description); + + // Note that problemDescriptor may be partially uninitialized, so we + // don't want to expose it directly to the user. So, we only provide + // the name and the original proto. + name = problemDescriptor.getName(); + proto = problemDescriptor.toProto(); + this.description = description; + } + } + + // ================================================================= + + /** + * A private helper class which contains lookup tables containing all the + * descriptors defined in a particular file. + */ + private static final class DescriptorPool { + DescriptorPool(final FileDescriptor[] dependencies) { + this.dependencies = new DescriptorPool[dependencies.length]; + + for (int i = 0; i < dependencies.length; i++) { + this.dependencies[i] = dependencies[i].pool; + } + + for (final FileDescriptor dependency : dependencies) { + try { + addPackage(dependency.getPackage(), dependency); + } catch (DescriptorValidationException e) { + // Can't happen, because addPackage() only fails when the name + // conflicts with a non-package, but we have not yet added any + // non-packages at this point. + assert false; + } + } + } + + private final DescriptorPool[] dependencies; + + private final Map descriptorsByName = + new HashMap(); + private final Map fieldsByNumber = + new HashMap(); + private final Map enumValuesByNumber + = new HashMap(); + + /** Find a generic descriptor by fully-qualified name. */ + GenericDescriptor findSymbol(final String fullName) { + GenericDescriptor result = descriptorsByName.get(fullName); + if (result != null) { + return result; + } + + for (final DescriptorPool dependency : dependencies) { + result = dependency.descriptorsByName.get(fullName); + if (result != null) { + return result; + } + } + + return null; + } + + /** + * Look up a descriptor by name, relative to some other descriptor. + * The name may be fully-qualified (with a leading '.'), + * partially-qualified, or unqualified. C++-like name lookup semantics + * are used to search for the matching descriptor. + */ + GenericDescriptor lookupSymbol(final String name, + final GenericDescriptor relativeTo) + throws DescriptorValidationException { + // TODO(kenton): This could be optimized in a number of ways. + + GenericDescriptor result; + if (name.startsWith(".")) { + // Fully-qualified name. + result = findSymbol(name.substring(1)); + } else { + // If "name" is a compound identifier, we want to search for the + // first component of it, then search within it for the rest. + final int firstPartLength = name.indexOf('.'); + final String firstPart; + if (firstPartLength == -1) { + firstPart = name; + } else { + firstPart = name.substring(0, firstPartLength); + } + + // We will search each parent scope of "relativeTo" looking for the + // symbol. + final StringBuilder scopeToTry = + new StringBuilder(relativeTo.getFullName()); + + while (true) { + // Chop off the last component of the scope. + final int dotpos = scopeToTry.lastIndexOf("."); + if (dotpos == -1) { + result = findSymbol(name); + break; + } else { + scopeToTry.setLength(dotpos + 1); + + // Append firstPart and try to find. + scopeToTry.append(firstPart); + result = findSymbol(scopeToTry.toString()); + + if (result != null) { + if (firstPartLength != -1) { + // We only found the first part of the symbol. Now look for + // the whole thing. If this fails, we *don't* want to keep + // searching parent scopes. + scopeToTry.setLength(dotpos + 1); + scopeToTry.append(name); + result = findSymbol(scopeToTry.toString()); + } + break; + } + + // Not found. Remove the name so we can try again. + scopeToTry.setLength(dotpos); + } + } + } + + if (result == null) { + throw new DescriptorValidationException(relativeTo, + '\"' + name + "\" is not defined."); + } else { + return result; + } + } + + /** + * Adds a symbol to the symbol table. If a symbol with the same name + * already exists, throws an error. + */ + void addSymbol(final GenericDescriptor descriptor) + throws DescriptorValidationException { + validateSymbolName(descriptor); + + final String fullName = descriptor.getFullName(); + final int dotpos = fullName.lastIndexOf('.'); + + final GenericDescriptor old = descriptorsByName.put(fullName, descriptor); + if (old != null) { + descriptorsByName.put(fullName, old); + + if (descriptor.getFile() == old.getFile()) { + if (dotpos == -1) { + throw new DescriptorValidationException(descriptor, + '\"' + fullName + "\" is already defined."); + } else { + throw new DescriptorValidationException(descriptor, + '\"' + fullName.substring(dotpos + 1) + + "\" is already defined in \"" + + fullName.substring(0, dotpos) + "\"."); + } + } else { + throw new DescriptorValidationException(descriptor, + '\"' + fullName + "\" is already defined in file \"" + + old.getFile().getName() + "\"."); + } + } + } + + /** + * Represents a package in the symbol table. We use PackageDescriptors + * just as placeholders so that someone cannot define, say, a message type + * that has the same name as an existing package. + */ + private static final class PackageDescriptor implements GenericDescriptor { + @Override + public Message toProto() { return file.toProto(); } + @Override + public String getName() { return name; } + @Override + public String getFullName() { return fullName; } + @Override + public FileDescriptor getFile() { return file; } + + PackageDescriptor(final String name, final String fullName, + final FileDescriptor file) { + this.file = file; + this.fullName = fullName; + this.name = name; + } + + private final String name; + private final String fullName; + private final FileDescriptor file; + } + + /** + * Adds a package to the symbol tables. If a package by the same name + * already exists, that is fine, but if some other kind of symbol exists + * under the same name, an exception is thrown. If the package has + * multiple components, this also adds the parent package(s). + */ + void addPackage(final String fullName, final FileDescriptor file) + throws DescriptorValidationException { + final int dotpos = fullName.lastIndexOf('.'); + final String name; + if (dotpos == -1) { + name = fullName; + } else { + addPackage(fullName.substring(0, dotpos), file); + name = fullName.substring(dotpos + 1); + } + + final GenericDescriptor old = + descriptorsByName.put(fullName, + new PackageDescriptor(name, fullName, file)); + if (old != null) { + descriptorsByName.put(fullName, old); + if (!(old instanceof PackageDescriptor)) { + throw new DescriptorValidationException(file, + '\"' + name + "\" is already defined (as something other than a " + + "package) in file \"" + old.getFile().getName() + "\"."); + } + } + } + + /** A (GenericDescriptor, int) pair, used as a map key. */ + private static final class DescriptorIntPair { + private final GenericDescriptor descriptor; + private final int number; + + DescriptorIntPair(final GenericDescriptor descriptor, final int number) { + this.descriptor = descriptor; + this.number = number; + } + + @Override + public int hashCode() { + return descriptor.hashCode() * ((1 << 16) - 1) + number; + } + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof DescriptorIntPair)) { + return false; + } + final DescriptorIntPair other = (DescriptorIntPair)obj; + return descriptor == other.descriptor && number == other.number; + } + } + + /** + * Adds a field to the fieldsByNumber table. Throws an exception if a + * field with hte same containing type and number already exists. + */ + void addFieldByNumber(final FieldDescriptor field) + throws DescriptorValidationException { + final DescriptorIntPair key = + new DescriptorIntPair(field.getContainingType(), field.getNumber()); + final FieldDescriptor old = fieldsByNumber.put(key, field); + if (old != null) { + fieldsByNumber.put(key, old); + throw new DescriptorValidationException(field, + "Field number " + field.getNumber() + + "has already been used in \"" + + field.getContainingType().getFullName() + + "\" by field \"" + old.getName() + "\"."); + } + } + + /** + * Adds an enum value to the enumValuesByNumber table. If an enum value + * with the same type and number already exists, does nothing. (This is + * allowed; the first value define with the number takes precedence.) + */ + void addEnumValueByNumber(final EnumValueDescriptor value) { + final DescriptorIntPair key = + new DescriptorIntPair(value.getType(), value.getNumber()); + final EnumValueDescriptor old = enumValuesByNumber.put(key, value); + if (old != null) { + enumValuesByNumber.put(key, old); + // Not an error: Multiple enum values may have the same number, but + // we only want the first one in the map. + } + } + + /** + * Verifies that the descriptor's name is valid (i.e. it contains only + * letters, digits, and underscores, and does not start with a digit). + */ + static void validateSymbolName(final GenericDescriptor descriptor) + throws DescriptorValidationException { + final String name = descriptor.getName(); + if (name.length() == 0) { + throw new DescriptorValidationException(descriptor, "Missing name."); + } else { + boolean valid = true; + for (int i = 0; i < name.length(); i++) { + final char c = name.charAt(i); + // Non-ASCII characters are not valid in protobuf identifiers, even + // if they are letters or digits. + if (c >= 128) { + valid = false; + } + // First character must be letter or _. Subsequent characters may + // be letters, numbers, or digits. + if (Character.isLetter(c) || c == '_' || + (Character.isDigit(c) && i > 0)) { + // Valid + } else { + valid = false; + } + } + if (!valid) { + throw new DescriptorValidationException(descriptor, + '\"' + name + "\" is not a valid identifier."); + } + } + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/DynamicMessage.java b/OsmAnd-java/src/com/google/protobuf/DynamicMessage.java new file mode 100644 index 0000000000..c64e609fd3 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/DynamicMessage.java @@ -0,0 +1,472 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; + +/** + * An implementation of {@link Message} that can represent arbitrary types, + * given a {@link Descriptors.Descriptor}. + * + * @author kenton@google.com Kenton Varda + */ +public final class DynamicMessage extends AbstractMessage { + private final Descriptor type; + private final FieldSet fields; + private final UnknownFieldSet unknownFields; + private int memoizedSize = -1; + + /** + * Construct a {@code DynamicMessage} using the given {@code FieldSet}. + */ + private DynamicMessage(Descriptor type, FieldSet fields, + UnknownFieldSet unknownFields) { + this.type = type; + this.fields = fields; + this.unknownFields = unknownFields; + } + + /** + * Get a {@code DynamicMessage} representing the default instance of the + * given type. + */ + public static DynamicMessage getDefaultInstance(Descriptor type) { + return new DynamicMessage(type, FieldSet.emptySet(), + UnknownFieldSet.getDefaultInstance()); + } + + /** Parse a message of the given type from the given input stream. */ + public static DynamicMessage parseFrom(Descriptor type, + CodedInputStream input) + throws IOException { + return newBuilder(type).mergeFrom(input).buildParsed(); + } + + /** Parse a message of the given type from the given input stream. */ + public static DynamicMessage parseFrom( + Descriptor type, + CodedInputStream input, + ExtensionRegistry extensionRegistry) + throws IOException { + return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed(); + } + + /** Parse {@code data} as a message of the given type and return it. */ + public static DynamicMessage parseFrom(Descriptor type, ByteString data) + throws InvalidProtocolBufferException { + return newBuilder(type).mergeFrom(data).buildParsed(); + } + + /** Parse {@code data} as a message of the given type and return it. */ + public static DynamicMessage parseFrom(Descriptor type, ByteString data, + ExtensionRegistry extensionRegistry) + throws InvalidProtocolBufferException { + return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed(); + } + + /** Parse {@code data} as a message of the given type and return it. */ + public static DynamicMessage parseFrom(Descriptor type, byte[] data) + throws InvalidProtocolBufferException { + return newBuilder(type).mergeFrom(data).buildParsed(); + } + + /** Parse {@code data} as a message of the given type and return it. */ + public static DynamicMessage parseFrom(Descriptor type, byte[] data, + ExtensionRegistry extensionRegistry) + throws InvalidProtocolBufferException { + return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed(); + } + + /** Parse a message of the given type from {@code input} and return it. */ + public static DynamicMessage parseFrom(Descriptor type, InputStream input) + throws IOException { + return newBuilder(type).mergeFrom(input).buildParsed(); + } + + /** Parse a message of the given type from {@code input} and return it. */ + public static DynamicMessage parseFrom(Descriptor type, InputStream input, + ExtensionRegistry extensionRegistry) + throws IOException { + return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed(); + } + + /** Construct a {@link Message.Builder} for the given type. */ + public static Builder newBuilder(Descriptor type) { + return new Builder(type); + } + + /** + * Construct a {@link Message.Builder} for a message of the same type as + * {@code prototype}, and initialize it with {@code prototype}'s contents. + */ + public static Builder newBuilder(Message prototype) { + return new Builder(prototype.getDescriptorForType()).mergeFrom(prototype); + } + + // ----------------------------------------------------------------- + // Implementation of Message interface. + + @Override +public Descriptor getDescriptorForType() { + return type; + } + + @Override +public DynamicMessage getDefaultInstanceForType() { + return getDefaultInstance(type); + } + + @Override +public Map getAllFields() { + return fields.getAllFields(); + } + + @Override +public boolean hasField(FieldDescriptor field) { + verifyContainingType(field); + return fields.hasField(field); + } + + @Override +public Object getField(FieldDescriptor field) { + verifyContainingType(field); + Object result = fields.getField(field); + if (result == null) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + result = getDefaultInstance(field.getMessageType()); + } else { + result = field.getDefaultValue(); + } + } + return result; + } + + @Override +public int getRepeatedFieldCount(FieldDescriptor field) { + verifyContainingType(field); + return fields.getRepeatedFieldCount(field); + } + + @Override +public Object getRepeatedField(FieldDescriptor field, int index) { + verifyContainingType(field); + return fields.getRepeatedField(field, index); + } + + @Override +public UnknownFieldSet getUnknownFields() { + return unknownFields; + } + + private static boolean isInitialized(Descriptor type, + FieldSet fields) { + // Check that all required fields are present. + for (final FieldDescriptor field : type.getFields()) { + if (field.isRequired()) { + if (!fields.hasField(field)) { + return false; + } + } + } + + // Check that embedded messages are initialized. + return fields.isInitialized(); + } + + @Override +public boolean isInitialized() { + return isInitialized(type, fields); + } + + @Override +public void writeTo(CodedOutputStream output) throws IOException { + if (type.getOptions().getMessageSetWireFormat()) { + fields.writeMessageSetTo(output); + unknownFields.writeAsMessageSetTo(output); + } else { + fields.writeTo(output); + unknownFields.writeTo(output); + } + } + + @Override +public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + if (type.getOptions().getMessageSetWireFormat()) { + size = fields.getMessageSetSerializedSize(); + size += unknownFields.getSerializedSizeAsMessageSet(); + } else { + size = fields.getSerializedSize(); + size += unknownFields.getSerializedSize(); + } + + memoizedSize = size; + return size; + } + + @Override +public Builder newBuilderForType() { + return new Builder(type); + } + + @Override +public Builder toBuilder() { + return newBuilderForType().mergeFrom(this); + } + + /** Verifies that the field is a field of this message. */ + private void verifyContainingType(FieldDescriptor field) { + if (field.getContainingType() != type) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } + } + + // ================================================================= + + /** + * Builder for {@link DynamicMessage}s. + */ + public static final class Builder extends AbstractMessage.Builder { + private final Descriptor type; + private FieldSet fields; + private UnknownFieldSet unknownFields; + + /** Construct a {@code Builder} for the given type. */ + private Builder(Descriptor type) { + this.type = type; + this.fields = FieldSet.newFieldSet(); + this.unknownFields = UnknownFieldSet.getDefaultInstance(); + } + + // --------------------------------------------------------------- + // Implementation of Message.Builder interface. + + @Override + public Builder clear() { + if (fields == null) { + throw new IllegalStateException("Cannot call clear() after build()."); + } + fields.clear(); + return this; + } + + @Override + public Builder mergeFrom(Message other) { + if (other instanceof DynamicMessage) { + // This should be somewhat faster than calling super.mergeFrom(). + DynamicMessage otherDynamicMessage = (DynamicMessage) other; + if (otherDynamicMessage.type != type) { + throw new IllegalArgumentException( + "mergeFrom(Message) can only merge messages of the same type."); + } + fields.mergeFrom(otherDynamicMessage.fields); + mergeUnknownFields(otherDynamicMessage.unknownFields); + return this; + } else { + return super.mergeFrom(other); + } + } + + @Override + public DynamicMessage build() { + // If fields == null, we'll throw an appropriate exception later. + if (fields != null && !isInitialized()) { + throw newUninitializedMessageException( + new DynamicMessage(type, fields, unknownFields)); + } + return buildPartial(); + } + + /** + * Helper for DynamicMessage.parseFrom() methods to call. Throws + * {@link InvalidProtocolBufferException} instead of + * {@link UninitializedMessageException}. + */ + private DynamicMessage buildParsed() throws InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + new DynamicMessage(type, fields, unknownFields)) + .asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public DynamicMessage buildPartial() { + if (fields == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + fields.makeImmutable(); + DynamicMessage result = + new DynamicMessage(type, fields, unknownFields); + fields = null; + unknownFields = null; + return result; + } + + @Override + public Builder clone() { + Builder result = new Builder(type); + result.fields.mergeFrom(fields); + return result; + } + + @Override + public boolean isInitialized() { + return DynamicMessage.isInitialized(type, fields); + } + + @Override + public Descriptor getDescriptorForType() { + return type; + } + + @Override + public DynamicMessage getDefaultInstanceForType() { + return getDefaultInstance(type); + } + + @Override + public Map getAllFields() { + return fields.getAllFields(); + } + + @Override + public Builder newBuilderForField(FieldDescriptor field) { + verifyContainingType(field); + + if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new IllegalArgumentException( + "newBuilderForField is only valid for fields with message type."); + } + + return new Builder(field.getMessageType()); + } + + @Override + public boolean hasField(FieldDescriptor field) { + verifyContainingType(field); + return fields.hasField(field); + } + + @Override + public Object getField(FieldDescriptor field) { + verifyContainingType(field); + Object result = fields.getField(field); + if (result == null) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + result = getDefaultInstance(field.getMessageType()); + } else { + result = field.getDefaultValue(); + } + } + return result; + } + + @Override + public Builder setField(FieldDescriptor field, Object value) { + verifyContainingType(field); + fields.setField(field, value); + return this; + } + + @Override + public Builder clearField(FieldDescriptor field) { + verifyContainingType(field); + fields.clearField(field); + return this; + } + + @Override + public int getRepeatedFieldCount(FieldDescriptor field) { + verifyContainingType(field); + return fields.getRepeatedFieldCount(field); + } + + @Override + public Object getRepeatedField(FieldDescriptor field, int index) { + verifyContainingType(field); + return fields.getRepeatedField(field, index); + } + + @Override + public Builder setRepeatedField(FieldDescriptor field, + int index, Object value) { + verifyContainingType(field); + fields.setRepeatedField(field, index, value); + return this; + } + + @Override + public Builder addRepeatedField(FieldDescriptor field, Object value) { + verifyContainingType(field); + fields.addRepeatedField(field, value); + return this; + } + + @Override + public UnknownFieldSet getUnknownFields() { + return unknownFields; + } + + @Override + public Builder setUnknownFields(UnknownFieldSet unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + @Override + public Builder mergeUnknownFields(UnknownFieldSet unknownFields) { + this.unknownFields = + UnknownFieldSet.newBuilder(this.unknownFields) + .mergeFrom(unknownFields) + .build(); + return this; + } + + /** Verifies that the field is a field of this message. */ + private void verifyContainingType(FieldDescriptor field) { + if (field.getContainingType() != type) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/ExtensionRegistry.java b/OsmAnd-java/src/com/google/protobuf/ExtensionRegistry.java new file mode 100644 index 0000000000..319c26f571 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/ExtensionRegistry.java @@ -0,0 +1,266 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; + +/** + * A table of known extensions, searchable by name or field number. When + * parsing a protocol message that might have extensions, you must provide + * an {@code ExtensionRegistry} in which you have registered any extensions + * that you want to be able to parse. Otherwise, those extensions will just + * be treated like unknown fields. + * + *

For example, if you had the {@code .proto} file: + * + *

+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ *   extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ *   optional int32 bar;
+ * }
+ * 
+ * + * Then you might write code like: + * + *
+ * ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ * registry.add(MyProto.bar);
+ * MyProto.Foo message = MyProto.Foo.parseFrom(input, registry);
+ * 
+ * + *

Background: + * + *

You might wonder why this is necessary. Two alternatives might come to + * mind. First, you might imagine a system where generated extensions are + * automatically registered when their containing classes are loaded. This + * is a popular technique, but is bad design; among other things, it creates a + * situation where behavior can change depending on what classes happen to be + * loaded. It also introduces a security vulnerability, because an + * unprivileged class could cause its code to be called unexpectedly from a + * privileged class by registering itself as an extension of the right type. + * + *

Another option you might consider is lazy parsing: do not parse an + * extension until it is first requested, at which point the caller must + * provide a type to use. This introduces a different set of problems. First, + * it would require a mutex lock any time an extension was accessed, which + * would be slow. Second, corrupt data would not be detected until first + * access, at which point it would be much harder to deal with it. Third, it + * could violate the expectation that message objects are immutable, since the + * type provided could be any arbitrary message class. An unprivileged user + * could take advantage of this to inject a mutable object into a message + * belonging to privileged code and create mischief. + * + * @author kenton@google.com Kenton Varda + */ +public final class ExtensionRegistry extends ExtensionRegistryLite { + /** Construct a new, empty instance. */ + public static ExtensionRegistry newInstance() { + return new ExtensionRegistry(); + } + + /** Get the unmodifiable singleton empty instance. */ + public static ExtensionRegistry getEmptyRegistry() { + return EMPTY; + } + + /** Returns an unmodifiable view of the registry. */ + @Override + public ExtensionRegistry getUnmodifiable() { + return new ExtensionRegistry(this); + } + + /** A (Descriptor, Message) pair, returned by lookup methods. */ + public static final class ExtensionInfo { + /** The extension's descriptor. */ + public final FieldDescriptor descriptor; + + /** + * A default instance of the extension's type, if it has a message type. + * Otherwise, {@code null}. + */ + public final Message defaultInstance; + + private ExtensionInfo(final FieldDescriptor descriptor) { + this.descriptor = descriptor; + defaultInstance = null; + } + private ExtensionInfo(final FieldDescriptor descriptor, + final Message defaultInstance) { + this.descriptor = descriptor; + this.defaultInstance = defaultInstance; + } + } + + /** + * Find an extension by fully-qualified field name, in the proto namespace. + * I.e. {@code result.descriptor.fullName()} will match {@code fullName} if + * a match is found. + * + * @return Information about the extension if found, or {@code null} + * otherwise. + */ + public ExtensionInfo findExtensionByName(final String fullName) { + return extensionsByName.get(fullName); + } + + /** + * Find an extension by containing type and field number. + * + * @return Information about the extension if found, or {@code null} + * otherwise. + */ + public ExtensionInfo findExtensionByNumber(final Descriptor containingType, + final int fieldNumber) { + return extensionsByNumber.get( + new DescriptorIntPair(containingType, fieldNumber)); + } + + /** Add an extension from a generated file to the registry. */ + public void add(final GeneratedMessage.GeneratedExtension extension) { + if (extension.getDescriptor().getJavaType() == + FieldDescriptor.JavaType.MESSAGE) { + if (extension.getMessageDefaultInstance() == null) { + throw new IllegalStateException( + "Registered message-type extension had null default instance: " + + extension.getDescriptor().getFullName()); + } + add(new ExtensionInfo(extension.getDescriptor(), + extension.getMessageDefaultInstance())); + } else { + add(new ExtensionInfo(extension.getDescriptor(), null)); + } + } + + /** Add a non-message-type extension to the registry by descriptor. */ + public void add(final FieldDescriptor type) { + if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + throw new IllegalArgumentException( + "ExtensionRegistry.add() must be provided a default instance when " + + "adding an embedded message extension."); + } + add(new ExtensionInfo(type, null)); + } + + /** Add a message-type extension to the registry by descriptor. */ + public void add(final FieldDescriptor type, final Message defaultInstance) { + if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new IllegalArgumentException( + "ExtensionRegistry.add() provided a default instance for a " + + "non-message extension."); + } + add(new ExtensionInfo(type, defaultInstance)); + } + + // ================================================================= + // Private stuff. + + private ExtensionRegistry() { + this.extensionsByName = new HashMap(); + this.extensionsByNumber = new HashMap(); + } + + private ExtensionRegistry(ExtensionRegistry other) { + super(other); + this.extensionsByName = Collections.unmodifiableMap(other.extensionsByName); + this.extensionsByNumber = + Collections.unmodifiableMap(other.extensionsByNumber); + } + + private final Map extensionsByName; + private final Map extensionsByNumber; + + private ExtensionRegistry(boolean empty) { + super(ExtensionRegistryLite.getEmptyRegistry()); + this.extensionsByName = Collections.emptyMap(); + this.extensionsByNumber = + Collections.emptyMap(); + } + private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true); + + private void add(final ExtensionInfo extension) { + if (!extension.descriptor.isExtension()) { + throw new IllegalArgumentException( + "ExtensionRegistry.add() was given a FieldDescriptor for a regular " + + "(non-extension) field."); + } + + extensionsByName.put(extension.descriptor.getFullName(), extension); + extensionsByNumber.put( + new DescriptorIntPair(extension.descriptor.getContainingType(), + extension.descriptor.getNumber()), + extension); + + final FieldDescriptor field = extension.descriptor; + if (field.getContainingType().getOptions().getMessageSetWireFormat() && + field.getType() == FieldDescriptor.Type.MESSAGE && + field.isOptional() && + field.getExtensionScope() == field.getMessageType()) { + // This is an extension of a MessageSet type defined within the extension + // type's own scope. For backwards-compatibility, allow it to be looked + // up by type name. + extensionsByName.put(field.getMessageType().getFullName(), extension); + } + } + + /** A (GenericDescriptor, int) pair, used as a map key. */ + private static final class DescriptorIntPair { + private final Descriptor descriptor; + private final int number; + + DescriptorIntPair(final Descriptor descriptor, final int number) { + this.descriptor = descriptor; + this.number = number; + } + + @Override + public int hashCode() { + return descriptor.hashCode() * ((1 << 16) - 1) + number; + } + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof DescriptorIntPair)) { + return false; + } + final DescriptorIntPair other = (DescriptorIntPair)obj; + return descriptor == other.descriptor && number == other.number; + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/ExtensionRegistryLite.java b/OsmAnd-java/src/com/google/protobuf/ExtensionRegistryLite.java new file mode 100644 index 0000000000..d5288dd8ef --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/ExtensionRegistryLite.java @@ -0,0 +1,169 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Equivalent to {@link ExtensionRegistry} but supports only "lite" types. + *

+ * If all of your types are lite types, then you only need to use + * {@code ExtensionRegistryLite}. Similarly, if all your types are regular + * types, then you only need {@link ExtensionRegistry}. Typically it does not + * make sense to mix the two, since if you have any regular types in your + * program, you then require the full runtime and lose all the benefits of + * the lite runtime, so you might as well make all your types be regular types. + * However, in some cases (e.g. when depending on multiple third-patry libraries + * where one uses lite types and one uses regular), you may find yourself + * wanting to mix the two. In this case things get more complicated. + *

+ * There are three factors to consider: Whether the type being extended is + * lite, whether the embedded type (in the case of a message-typed extension) + * is lite, and whether the extension itself is lite. Since all three are + * declared in different files, they could all be different. Here are all + * the combinations and which type of registry to use: + *

+ *   Extended type     Inner type    Extension         Use registry
+ *   =======================================================================
+ *   lite              lite          lite              ExtensionRegistryLite
+ *   lite              regular       lite              ExtensionRegistry
+ *   regular           regular       regular           ExtensionRegistry
+ *   all other combinations                            not supported
+ * 
+ *

+ * Note that just as regular types are not allowed to contain lite-type fields, + * they are also not allowed to contain lite-type extensions. This is because + * regular types must be fully accessible via reflection, which in turn means + * that all the inner messages must also support reflection. On the other hand, + * since regular types implement the entire lite interface, there is no problem + * with embedding regular types inside lite types. + * + * @author kenton@google.com Kenton Varda + */ +public class ExtensionRegistryLite { + /** Construct a new, empty instance. */ + public static ExtensionRegistryLite newInstance() { + return new ExtensionRegistryLite(); + } + + /** Get the unmodifiable singleton empty instance. */ + public static ExtensionRegistryLite getEmptyRegistry() { + return EMPTY; + } + + /** Returns an unmodifiable view of the registry. */ + public ExtensionRegistryLite getUnmodifiable() { + return new ExtensionRegistryLite(this); + } + + /** + * Find an extension by containing type and field number. + * + * @return Information about the extension if found, or {@code null} + * otherwise. + */ + @SuppressWarnings("unchecked") + public + GeneratedMessageLite.GeneratedExtension + findLiteExtensionByNumber( + final ContainingType containingTypeDefaultInstance, + final int fieldNumber) { + return (GeneratedMessageLite.GeneratedExtension) + extensionsByNumber.get( + new ObjectIntPair(containingTypeDefaultInstance, fieldNumber)); + } + + /** Add an extension from a lite generated file to the registry. */ + public final void add( + final GeneratedMessageLite.GeneratedExtension extension) { + extensionsByNumber.put( + new ObjectIntPair(extension.getContainingTypeDefaultInstance(), + extension.getNumber()), + extension); + } + + // ================================================================= + // Private stuff. + + // Constructors are package-private so that ExtensionRegistry can subclass + // this. + + ExtensionRegistryLite() { + this.extensionsByNumber = + new HashMap>(); + } + + ExtensionRegistryLite(ExtensionRegistryLite other) { + if (other == EMPTY) { + this.extensionsByNumber = Collections.emptyMap(); + } else { + this.extensionsByNumber = + Collections.unmodifiableMap(other.extensionsByNumber); + } + } + + private final Map> + extensionsByNumber; + + private ExtensionRegistryLite(boolean empty) { + this.extensionsByNumber = Collections.emptyMap(); + } + private static final ExtensionRegistryLite EMPTY = + new ExtensionRegistryLite(true); + + /** A (Object, int) pair, used as a map key. */ + private static final class ObjectIntPair { + private final Object object; + private final int number; + + ObjectIntPair(final Object object, final int number) { + this.object = object; + this.number = number; + } + + @Override + public int hashCode() { + return System.identityHashCode(object) * ((1 << 16) - 1) + number; + } + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof ObjectIntPair)) { + return false; + } + final ObjectIntPair other = (ObjectIntPair)obj; + return object == other.object && number == other.number; + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/FieldSet.java b/OsmAnd-java/src/com/google/protobuf/FieldSet.java new file mode 100644 index 0000000000..a76c04f5fa --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/FieldSet.java @@ -0,0 +1,715 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * A class which represents an arbitrary set of fields of some message type. + * This is used to implement {@link DynamicMessage}, and also to represent + * extensions in {@link GeneratedMessage}. This class is package-private, + * since outside users should probably be using {@link DynamicMessage}. + * + * @author kenton@google.com Kenton Varda + */ +final class FieldSet> { + /** + * Interface for a FieldDescriptor or lite extension descriptor. This + * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}. + */ + public interface FieldDescriptorLite> + extends Comparable { + int getNumber(); + WireFormat.FieldType getLiteType(); + WireFormat.JavaType getLiteJavaType(); + boolean isRepeated(); + boolean isPacked(); + Internal.EnumLiteMap getEnumType(); + + // If getLiteJavaType() == MESSAGE, this merges a message object of the + // type into a builder of the type. Returns {@code to}. + MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from); + } + + private Map fields; + + /** Construct a new FieldSet. */ + private FieldSet() { + // Use a TreeMap because fields need to be in canonical order when + // serializing. + // TODO(kenton): Maybe use some sort of sparse array instead? It would + // even make sense to store the first 16 or so tags in a flat array + // to make DynamicMessage faster. + fields = new TreeMap(); + } + + /** + * Construct an empty FieldSet. This is only used to initialize + * DEFAULT_INSTANCE. + */ + private FieldSet(final boolean dummy) { + this.fields = Collections.emptyMap(); + } + + /** Construct a new FieldSet. */ + public static > + FieldSet newFieldSet() { + return new FieldSet(); + } + + /** Get an immutable empty FieldSet. */ + @SuppressWarnings("unchecked") + public static > + FieldSet emptySet() { + return DEFAULT_INSTANCE; + } + @SuppressWarnings("unchecked") + private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true); + + /** Make this FieldSet immutable from this point forward. */ + @SuppressWarnings("unchecked") + public void makeImmutable() { + for (final Map.Entry entry: + fields.entrySet()) { + if (entry.getKey().isRepeated()) { + final List value = (List)entry.getValue(); + fields.put(entry.getKey(), Collections.unmodifiableList(value)); + } + } + fields = Collections.unmodifiableMap(fields); + } + + // ================================================================= + + /** See {@link Message.Builder#clear()}. */ + public void clear() { + fields.clear(); + } + + /** + * Get a simple map containing all the fields. + */ + public Map getAllFields() { + return Collections.unmodifiableMap(fields); + } + + /** + * Get an iterator to the field map. This iterator should not be leaked + * out of the protobuf library as it is not protected from mutation. + */ + public Iterator> iterator() { + return fields.entrySet().iterator(); + } + + /** + * Useful for implementing + * {@link Message#hasField(Descriptors.FieldDescriptor)}. + */ + public boolean hasField(final FieldDescriptorType descriptor) { + if (descriptor.isRepeated()) { + throw new IllegalArgumentException( + "hasField() can only be called on non-repeated fields."); + } + + return fields.get(descriptor) != null; + } + + /** + * Useful for implementing + * {@link Message#getField(Descriptors.FieldDescriptor)}. This method + * returns {@code null} if the field is not set; in this case it is up + * to the caller to fetch the field's default value. + */ + public Object getField(final FieldDescriptorType descriptor) { + return fields.get(descriptor); + } + + /** + * Useful for implementing + * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. + */ + @SuppressWarnings("unchecked") + public void setField(final FieldDescriptorType descriptor, + Object value) { + if (descriptor.isRepeated()) { + if (!(value instanceof List)) { + throw new IllegalArgumentException( + "Wrong object type used with protocol message reflection."); + } + + // Wrap the contents in a new list so that the caller cannot change + // the list's contents after setting it. + final List newList = new ArrayList(); + newList.addAll((List)value); + for (final Object element : newList) { + verifyType(descriptor.getLiteType(), element); + } + value = newList; + } else { + verifyType(descriptor.getLiteType(), value); + } + + fields.put(descriptor, value); + } + + /** + * Useful for implementing + * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}. + */ + public void clearField(final FieldDescriptorType descriptor) { + fields.remove(descriptor); + } + + /** + * Useful for implementing + * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}. + */ + public int getRepeatedFieldCount(final FieldDescriptorType descriptor) { + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "getRepeatedField() can only be called on repeated fields."); + } + + final Object value = fields.get(descriptor); + if (value == null) { + return 0; + } else { + return ((List) value).size(); + } + } + + /** + * Useful for implementing + * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}. + */ + @SuppressWarnings("unchecked") +public Object getRepeatedField(final FieldDescriptorType descriptor, + final int index) { + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "getRepeatedField() can only be called on repeated fields."); + } + + final Object value = fields.get(descriptor); + + if (value == null) { + throw new IndexOutOfBoundsException(); + } else { + return ((List) value).get(index); + } + } + + /** + * Useful for implementing + * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}. + */ + @SuppressWarnings("unchecked") + public void setRepeatedField(final FieldDescriptorType descriptor, + final int index, + final Object value) { + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "getRepeatedField() can only be called on repeated fields."); + } + + final Object list = fields.get(descriptor); + if (list == null) { + throw new IndexOutOfBoundsException(); + } + + verifyType(descriptor.getLiteType(), value); + ((List) list).set(index, value); + } + + /** + * Useful for implementing + * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}. + */ + @SuppressWarnings("unchecked") + public void addRepeatedField(final FieldDescriptorType descriptor, + final Object value) { + if (!descriptor.isRepeated()) { + throw new IllegalArgumentException( + "addRepeatedField() can only be called on repeated fields."); + } + + verifyType(descriptor.getLiteType(), value); + + final Object existingValue = fields.get(descriptor); + List list; + if (existingValue == null) { + list = new ArrayList(); + fields.put(descriptor, list); + } else { + list = (List) existingValue; + } + + list.add(value); + } + + /** + * Verifies that the given object is of the correct type to be a valid + * value for the given field. (For repeated fields, this checks if the + * object is the right type to be one element of the field.) + * + * @throws IllegalArgumentException The value is not of the right type. + */ + private static void verifyType(final WireFormat.FieldType type, + final Object value) { + if (value == null) { + throw new NullPointerException(); + } + + boolean isValid = false; + switch (type.getJavaType()) { + case INT: isValid = value instanceof Integer ; break; + case LONG: isValid = value instanceof Long ; break; + case FLOAT: isValid = value instanceof Float ; break; + case DOUBLE: isValid = value instanceof Double ; break; + case BOOLEAN: isValid = value instanceof Boolean ; break; + case STRING: isValid = value instanceof String ; break; + case BYTE_STRING: isValid = value instanceof ByteString; break; + case ENUM: + // TODO(kenton): Caller must do type checking here, I guess. + isValid = value instanceof Internal.EnumLite; + break; + case MESSAGE: + // TODO(kenton): Caller must do type checking here, I guess. + isValid = value instanceof MessageLite; + break; + } + + if (!isValid) { + // TODO(kenton): When chaining calls to setField(), it can be hard to + // tell from the stack trace which exact call failed, since the whole + // chain is considered one line of code. It would be nice to print + // more information here, e.g. naming the field. We used to do that. + // But we can't now that FieldSet doesn't use descriptors. Maybe this + // isn't a big deal, though, since it would only really apply when using + // reflection and generally people don't chain reflection setters. + throw new IllegalArgumentException( + "Wrong object type used with protocol message reflection."); + } + } + + // ================================================================= + // Parsing and serialization + + /** + * See {@link Message#isInitialized()}. Note: Since {@code FieldSet} + * itself does not have any way of knowing about required fields that + * aren't actually present in the set, it is up to the caller to check + * that all required fields are present. + */ + @SuppressWarnings("unchecked") + public boolean isInitialized() { + for (final Map.Entry entry: + fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + if (descriptor.isRepeated()) { + for (final MessageLite element: + (List) entry.getValue()) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (!((MessageLite) entry.getValue()).isInitialized()) { + return false; + } + } + } + } + + return true; + } + + /** + * Given a field type, return the wire type. + * + * @returns One of the {@code WIRETYPE_} constants defined in + * {@link WireFormat}. + */ + static int getWireFormatForFieldType(final WireFormat.FieldType type, + boolean isPacked) { + if (isPacked) { + return WireFormat.WIRETYPE_LENGTH_DELIMITED; + } else { + return type.getWireType(); + } + } + + /** + * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}. + */ + @SuppressWarnings("unchecked") + public void mergeFrom(final FieldSet other) { + for (final Map.Entry entry: + other.fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + final Object otherValue = entry.getValue(); + + if (descriptor.isRepeated()) { + Object value = fields.get(descriptor); + if (value == null) { + // Our list is empty, but we still need to make a defensive copy of + // the other list since we don't know if the other FieldSet is still + // mutable. + fields.put(descriptor, new ArrayList((List) otherValue)); + } else { + // Concatenate the lists. + ((List) value).addAll((List) otherValue); + } + } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { + Object value = fields.get(descriptor); + if (value == null) { + fields.put(descriptor, otherValue); + } else { + // Merge the messages. + fields.put(descriptor, + descriptor.internalMergeFrom( + ((MessageLite) value).toBuilder(), (MessageLite) otherValue) + .build()); + } + + } else { + fields.put(descriptor, otherValue); + } + } + } + + // TODO(kenton): Move static parsing and serialization methods into some + // other class. Probably WireFormat. + + /** + * Read a field of any primitive type from a CodedInputStream. Enums, + * groups, and embedded messages are not handled by this method. + * + * @param input The stream from which to read. + * @param type Declared type of the field. + * @return An object representing the field's value, of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + public static Object readPrimitiveField( + CodedInputStream input, + final WireFormat.FieldType type) throws IOException { + switch (type) { + case DOUBLE : return input.readDouble (); + case FLOAT : return input.readFloat (); + case INT64 : return input.readInt64 (); + case UINT64 : return input.readUInt64 (); + case INT32 : return input.readInt32 (); + case FIXED64 : return input.readFixed64 (); + case FIXED32 : return input.readFixed32 (); + case BOOL : return input.readBool (); + case STRING : return input.readString (); + case BYTES : return input.readBytes (); + case UINT32 : return input.readUInt32 (); + case SFIXED32: return input.readSFixed32(); + case SFIXED64: return input.readSFixed64(); + case SINT32 : return input.readSInt32 (); + case SINT64 : return input.readSInt64 (); + + case GROUP: + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle nested groups."); + case MESSAGE: + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle embedded messages."); + case ENUM: + // We don't handle enums because we don't know what to do if the + // value is not recognized. + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle enums."); + } + + throw new RuntimeException( + "There is no way to get here, but the compiler thinks otherwise."); + } + + /** See {@link Message#writeTo(CodedOutputStream)}. */ + public void writeTo(final CodedOutputStream output) + throws IOException { + for (final Map.Entry entry: + fields.entrySet()) { + writeField(entry.getKey(), entry.getValue(), output); + } + } + + /** + * Like {@link #writeTo} but uses MessageSet wire format. + */ + public void writeMessageSetTo(final CodedOutputStream output) + throws IOException { + for (final Map.Entry entry: + fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated() && !descriptor.isPacked()) { + output.writeMessageSetExtension(entry.getKey().getNumber(), + (MessageLite) entry.getValue()); + } else { + writeField(descriptor, entry.getValue(), output); + } + } + } + + /** + * Write a single tag-value pair to the stream. + * + * @param output The output stream. + * @param type The field's type. + * @param number The field's number. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static void writeElement(final CodedOutputStream output, + final WireFormat.FieldType type, + final int number, + final Object value) throws IOException { + // Special case for groups, which need a start and end tag; other fields + // can just use writeTag() and writeFieldNoTag(). + if (type == WireFormat.FieldType.GROUP) { + output.writeGroup(number, (MessageLite) value); + } else { + output.writeTag(number, getWireFormatForFieldType(type, false)); + writeElementNoTag(output, type, value); + } + } + + /** + * Write a field of arbitrary type, without its tag, to the stream. + * + * @param output The output stream. + * @param type The field's type. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static void writeElementNoTag( + final CodedOutputStream output, + final WireFormat.FieldType type, + final Object value) throws IOException { + switch (type) { + case DOUBLE : output.writeDoubleNoTag ((Double ) value); break; + case FLOAT : output.writeFloatNoTag ((Float ) value); break; + case INT64 : output.writeInt64NoTag ((Long ) value); break; + case UINT64 : output.writeUInt64NoTag ((Long ) value); break; + case INT32 : output.writeInt32NoTag ((Integer ) value); break; + case FIXED64 : output.writeFixed64NoTag ((Long ) value); break; + case FIXED32 : output.writeFixed32NoTag ((Integer ) value); break; + case BOOL : output.writeBoolNoTag ((Boolean ) value); break; + case STRING : output.writeStringNoTag ((String ) value); break; + case GROUP : output.writeGroupNoTag ((MessageLite) value); break; + case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break; + case BYTES : output.writeBytesNoTag ((ByteString ) value); break; + case UINT32 : output.writeUInt32NoTag ((Integer ) value); break; + case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break; + case SFIXED64: output.writeSFixed64NoTag((Long ) value); break; + case SINT32 : output.writeSInt32NoTag ((Integer ) value); break; + case SINT64 : output.writeSInt64NoTag ((Long ) value); break; + + case ENUM: + output.writeEnumNoTag(((Internal.EnumLite) value).getNumber()); + break; + } + } + + /** Write a single field. */ + @SuppressWarnings("unchecked") +public static void writeField(final FieldDescriptorLite descriptor, + final Object value, + final CodedOutputStream output) + throws IOException { + WireFormat.FieldType type = descriptor.getLiteType(); + int number = descriptor.getNumber(); + if (descriptor.isRepeated()) { + final List valueList = (List)value; + if (descriptor.isPacked()) { + output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED); + // Compute the total data size so the length can be written. + int dataSize = 0; + for (final Object element : valueList) { + dataSize += computeElementSizeNoTag(type, element); + } + output.writeRawVarint32(dataSize); + // Write the data itself, without any tags. + for (final Object element : valueList) { + writeElementNoTag(output, type, element); + } + } else { + for (final Object element : valueList) { + writeElement(output, type, number, element); + } + } + } else { + writeElement(output, type, number, value); + } + } + + /** + * See {@link Message#getSerializedSize()}. It's up to the caller to cache + * the resulting size if desired. + */ + public int getSerializedSize() { + int size = 0; + for (final Map.Entry entry: + fields.entrySet()) { + size += computeFieldSize(entry.getKey(), entry.getValue()); + } + return size; + } + + /** + * Like {@link #getSerializedSize} but uses MessageSet wire format. + */ + public int getMessageSetSerializedSize() { + int size = 0; + for (final Map.Entry entry: + fields.entrySet()) { + final FieldDescriptorType descriptor = entry.getKey(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated() && !descriptor.isPacked()) { + size += CodedOutputStream.computeMessageSetExtensionSize( + entry.getKey().getNumber(), (MessageLite) entry.getValue()); + } else { + size += computeFieldSize(descriptor, entry.getValue()); + } + } + return size; + } + + /** + * Compute the number of bytes that would be needed to encode a + * single tag/value pair of arbitrary type. + * + * @param type The field's type. + * @param number The field's number. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static int computeElementSize( + final WireFormat.FieldType type, + final int number, final Object value) { + int tagSize = CodedOutputStream.computeTagSize(number); + if (type == WireFormat.FieldType.GROUP) { + tagSize *= 2; + } + return tagSize + computeElementSizeNoTag(type, value); + } + + /** + * Compute the number of bytes that would be needed to encode a + * particular value of arbitrary type, excluding tag. + * + * @param type The field's type. + * @param value Object representing the field's value. Must be of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + private static int computeElementSizeNoTag( + final WireFormat.FieldType type, final Object value) { + switch (type) { + // Note: Minor violation of 80-char limit rule here because this would + // actually be harder to read if we wrapped the lines. + case DOUBLE : return CodedOutputStream.computeDoubleSizeNoTag ((Double )value); + case FLOAT : return CodedOutputStream.computeFloatSizeNoTag ((Float )value); + case INT64 : return CodedOutputStream.computeInt64SizeNoTag ((Long )value); + case UINT64 : return CodedOutputStream.computeUInt64SizeNoTag ((Long )value); + case INT32 : return CodedOutputStream.computeInt32SizeNoTag ((Integer )value); + case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long )value); + case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer )value); + case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value); + case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value); + case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value); + case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value); + case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value); + case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value); + case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value); + case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value); + case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value); + case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value); + + case ENUM: + return CodedOutputStream.computeEnumSizeNoTag( + ((Internal.EnumLite) value).getNumber()); + } + + throw new RuntimeException( + "There is no way to get here, but the compiler thinks otherwise."); + } + + /** + * Compute the number of bytes needed to encode a particular field. + */ + @SuppressWarnings("unchecked") +public static int computeFieldSize(final FieldDescriptorLite descriptor, + final Object value) { + WireFormat.FieldType type = descriptor.getLiteType(); + int number = descriptor.getNumber(); + if (descriptor.isRepeated()) { + if (descriptor.isPacked()) { + int dataSize = 0; + for (final Object element : (List)value) { + dataSize += computeElementSizeNoTag(type, element); + } + return dataSize + + CodedOutputStream.computeTagSize(number) + + CodedOutputStream.computeRawVarint32Size(dataSize); + } else { + int size = 0; + for (final Object element : (List)value) { + size += computeElementSize(type, number, element); + } + return size; + } + } else { + return computeElementSize(type, number, value); + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/GeneratedMessage.java b/OsmAnd-java/src/com/google/protobuf/GeneratedMessage.java new file mode 100644 index 0000000000..53dc17e777 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/GeneratedMessage.java @@ -0,0 +1,1370 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.EnumValueDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; + +/** + * All generated protocol message classes extend this class. This class + * implements most of the Message and Builder interfaces using Java reflection. + * Users can ignore this class and pretend that generated messages implement + * the Message interface directly. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class GeneratedMessage extends AbstractMessage { + protected GeneratedMessage() {} + + private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance(); + + /** + * Get the FieldAccessorTable for this type. We can't have the message + * class pass this in to the constructor because of bootstrapping trouble + * with DescriptorProtos. + */ + protected abstract FieldAccessorTable internalGetFieldAccessorTable(); + + @Override +public Descriptor getDescriptorForType() { + return internalGetFieldAccessorTable().descriptor; + } + + /** Internal helper which returns a mutable map. */ + @SuppressWarnings("unchecked") +private Map getAllFieldsMutable() { + final TreeMap result = + new TreeMap(); + final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; + for (final FieldDescriptor field : descriptor.getFields()) { + if (field.isRepeated()) { + final List value = (List) getField(field); + if (!value.isEmpty()) { + result.put(field, value); + } + } else { + if (hasField(field)) { + result.put(field, getField(field)); + } + } + } + return result; + } + + @Override + public boolean isInitialized() { + for (final FieldDescriptor field : getDescriptorForType().getFields()) { + // Check that all required fields are present. + if (field.isRequired()) { + if (!hasField(field)) { + return false; + } + } + // Check that embedded messages are initialized. + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + // Osmand fix (remove annotation) + final + List messageList = (List) getField(field); + for (final Message element : messageList) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (hasField(field) && !((Message) getField(field)).isInitialized()) { + return false; + } + } + } + } + + return true; + } + + @Override +public Map getAllFields() { + return Collections.unmodifiableMap(getAllFieldsMutable()); + } + + @Override +public boolean hasField(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).has(this); + } + + @Override +public Object getField(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).get(this); + } + + @Override +public int getRepeatedFieldCount(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field) + .getRepeatedCount(this); + } + + @Override +public Object getRepeatedField(final FieldDescriptor field, final int index) { + return internalGetFieldAccessorTable().getField(field) + .getRepeated(this, index); + } + + @Override +public final UnknownFieldSet getUnknownFields() { + return unknownFields; + } + + @SuppressWarnings("unchecked") + public abstract static class Builder + extends AbstractMessage.Builder { + protected Builder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** + * Get the message being built. We don't just pass this to the + * constructor because it becomes null when build() is called. + */ + protected abstract GeneratedMessage internalGetResult(); + + /** + * Get the FieldAccessorTable for this type. We can't have the message + * class pass this in to the constructor because of bootstrapping trouble + * with DescriptorProtos. + */ + private FieldAccessorTable internalGetFieldAccessorTable() { + return internalGetResult().internalGetFieldAccessorTable(); + } + + @Override + public Descriptor getDescriptorForType() { + return internalGetFieldAccessorTable().descriptor; + } + + @Override + public Map getAllFields() { + return internalGetResult().getAllFields(); + } + + @Override + public Message.Builder newBuilderForField( + final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).newBuilder(); + } + + @Override + public boolean hasField(final FieldDescriptor field) { + return internalGetResult().hasField(field); + } + + @Override + public Object getField(final FieldDescriptor field) { + if (field.isRepeated()) { + // The underlying list object is still modifiable at this point. + // Make sure not to expose the modifiable list to the caller. + return Collections.unmodifiableList( + (List) internalGetResult().getField(field)); + } else { + return internalGetResult().getField(field); + } + } + + @Override + public BuilderType setField(final FieldDescriptor field, + final Object value) { + internalGetFieldAccessorTable().getField(field).set(this, value); + return (BuilderType) this; + } + + @Override + public BuilderType clearField(final FieldDescriptor field) { + internalGetFieldAccessorTable().getField(field).clear(this); + return (BuilderType) this; + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + return internalGetResult().getRepeatedFieldCount(field); + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, + final int index) { + return internalGetResult().getRepeatedField(field, index); + } + + @Override + public BuilderType setRepeatedField(final FieldDescriptor field, + final int index, final Object value) { + internalGetFieldAccessorTable().getField(field) + .setRepeated(this, index, value); + return (BuilderType) this; + } + + @Override + public BuilderType addRepeatedField(final FieldDescriptor field, + final Object value) { + internalGetFieldAccessorTable().getField(field).addRepeated(this, value); + return (BuilderType) this; + } + + @Override + public final UnknownFieldSet getUnknownFields() { + return internalGetResult().unknownFields; + } + + @Override + public final BuilderType setUnknownFields( + final UnknownFieldSet unknownFields) { + internalGetResult().unknownFields = unknownFields; + return (BuilderType) this; + } + + @Override + public final BuilderType mergeUnknownFields( + final UnknownFieldSet unknownFields) { + final GeneratedMessage result = internalGetResult(); + result.unknownFields = + UnknownFieldSet.newBuilder(result.unknownFields) + .mergeFrom(unknownFields) + .build(); + return (BuilderType) this; + } + + @Override + public boolean isInitialized() { + return internalGetResult().isInitialized(); + } + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + return unknownFields.mergeFieldFrom(tag, input); + } + } + + // ================================================================= + // Extensions-related stuff + + /** + * Generated message classes for message types that contain extension ranges + * subclass this. + * + *

This class implements type-safe accessors for extensions. They + * implement all the same operations that you can do with normal fields -- + * e.g. "has", "get", and "getCount" -- but for extensions. The extensions + * are identified using instances of the class {@link GeneratedExtension}; + * the protocol compiler generates a static instance of this class for every + * extension in its input. Through the magic of generics, all is made + * type-safe. + * + *

For example, imagine you have the {@code .proto} file: + * + *

+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * 
+ * + *

Then you might write code like: + * + *

+   * MyProto.Foo foo = getFoo();
+   * int i = foo.getExtension(MyProto.bar);
+   * 
+ * + *

See also {@link ExtendableBuilder}. + */ + public abstract static class ExtendableMessage< + MessageType extends ExtendableMessage> + extends GeneratedMessage { + protected ExtendableMessage() {} + private final FieldSet extensions = FieldSet.newFieldSet(); + + private void verifyExtensionContainingType( + final GeneratedExtension extension) { + if (extension.getDescriptor().getContainingType() != + getDescriptorForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "Extension is for type \"" + + extension.getDescriptor().getContainingType().getFullName() + + "\" which does not match message type \"" + + getDescriptorForType().getFullName() + "\"."); + } + } + + /** Check if a singular extension is present. */ + public final boolean hasExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + return extensions.hasField(extension.getDescriptor()); + } + + /** Get the number of elements in a repeated extension. */ + public final int getExtensionCount( + // osmand fix >> -> > > + final GeneratedExtension > extension) { + verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + return extensions.getRepeatedFieldCount(descriptor); + } + + /** Get the value of an extension. */ + @SuppressWarnings("unchecked") + public final Type getExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + final Object value = extensions.getField(descriptor); + if (value == null) { + if (descriptor.isRepeated()) { + return (Type) Collections.emptyList(); + } else if (descriptor.getJavaType() == + FieldDescriptor.JavaType.MESSAGE) { + return (Type) extension.getMessageDefaultInstance(); + } else { + return (Type) extension.fromReflectionType( + descriptor.getDefaultValue()); + } + } else { + return (Type) extension.fromReflectionType(value); + } + } + + /** Get one element of a repeated extension. */ + @SuppressWarnings("unchecked") + public final Type getExtension( + // osmand fix >> -> > > + final GeneratedExtension > extension, + final int index) { + verifyExtensionContainingType(extension); + FieldDescriptor descriptor = extension.getDescriptor(); + return (Type) extension.singularFromReflectionType( + extensions.getRepeatedField(descriptor, index)); + } + + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + + @Override + public boolean isInitialized() { + return super.isInitialized() && extensionsAreInitialized(); + } + + /** + * Used by subclasses to serialize extensions. Extension ranges may be + * interleaved with field numbers, but we must write them in canonical + * (sorted by field number) order. ExtensionWriter helps us write + * individual ranges of extensions at once. + */ + protected class ExtensionWriter { + // Imagine how much simpler this code would be if Java iterators had + // a way to get the next element without advancing the iterator. + // osmand fix >> -> > > + private final Iterator > iter = + extensions.iterator(); + private Map.Entry next; + private final boolean messageSetWireFormat; + + private ExtensionWriter(final boolean messageSetWireFormat) { + if (iter.hasNext()) { + next = iter.next(); + } + this.messageSetWireFormat = messageSetWireFormat; + } + + public void writeUntil(final int end, final CodedOutputStream output) + throws IOException { + while (next != null && next.getKey().getNumber() < end) { + FieldDescriptor descriptor = next.getKey(); + if (messageSetWireFormat && descriptor.getLiteJavaType() == + WireFormat.JavaType.MESSAGE && + !descriptor.isRepeated()) { + output.writeMessageSetExtension(descriptor.getNumber(), + (Message) next.getValue()); + } else { + FieldSet.writeField(descriptor, next.getValue(), output); + } + if (iter.hasNext()) { + next = iter.next(); + } else { + next = null; + } + } + } + } + + protected ExtensionWriter newExtensionWriter() { + return new ExtensionWriter(false); + } + protected ExtensionWriter newMessageSetExtensionWriter() { + return new ExtensionWriter(true); + } + + /** Called by subclasses to compute the size of extensions. */ + protected int extensionsSerializedSize() { + return extensions.getSerializedSize(); + } + protected int extensionsSerializedSizeAsMessageSet() { + return extensions.getMessageSetSerializedSize(); + } + + // --------------------------------------------------------------- + // Reflection + + @Override + public Map getAllFields() { + final Map result = super.getAllFieldsMutable(); + result.putAll(extensions.getAllFields()); + return Collections.unmodifiableMap(result); + } + + @Override + public boolean hasField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.hasField(field); + } else { + return super.hasField(field); + } + } + + @Override + public Object getField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + final Object value = extensions.getField(field); + if (value == null) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + // Lacking an ExtensionRegistry, we have no way to determine the + // extension's real type, so we return a DynamicMessage. + return DynamicMessage.getDefaultInstance(field.getMessageType()); + } else { + return field.getDefaultValue(); + } + } else { + return value; + } + } else { + return super.getField(field); + } + } + + @Override + public int getRepeatedFieldCount(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedFieldCount(field); + } else { + return super.getRepeatedFieldCount(field); + } + } + + @Override + public Object getRepeatedField(final FieldDescriptor field, + final int index) { + if (field.isExtension()) { + verifyContainingType(field); + return extensions.getRepeatedField(field, index); + } else { + return super.getRepeatedField(field, index); + } + } + + private void verifyContainingType(final FieldDescriptor field) { + if (field.getContainingType() != getDescriptorForType()) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } + } + } + + /** + * Generated message builders for message types that contain extension ranges + * subclass this. + * + *

This class implements type-safe accessors for extensions. They + * implement all the same operations that you can do with normal fields -- + * e.g. "get", "set", and "add" -- but for extensions. The extensions are + * identified using instances of the class {@link GeneratedExtension}; the + * protocol compiler generates a static instance of this class for every + * extension in its input. Through the magic of generics, all is made + * type-safe. + * + *

For example, imagine you have the {@code .proto} file: + * + *

+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * 
+ * + *

Then you might write code like: + * + *

+   * MyProto.Foo foo =
+   *   MyProto.Foo.newBuilder()
+   *     .setExtension(MyProto.bar, 123)
+   *     .build();
+   * 
+ * + *

See also {@link ExtendableMessage}. + */ + @SuppressWarnings("unchecked") + public abstract static class ExtendableBuilder< + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends Builder { + protected ExtendableBuilder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + @Override + protected abstract ExtendableMessage internalGetResult(); + + /** Check if a singular extension is present. */ + public final boolean hasExtension( + final GeneratedExtension extension) { + return internalGetResult().hasExtension(extension); + } + + /** Get the number of elements in a repeated extension. */ + public final int getExtensionCount( + // osmand fix >> -> > > + final GeneratedExtension > extension) { + return internalGetResult().getExtensionCount(extension); + } + + /** Get the value of an extension. */ + public final Type getExtension( + final GeneratedExtension extension) { + return internalGetResult().getExtension(extension); + } + + /** Get one element of a repeated extension. */ + public final Type getExtension( + // osmand fix >> -> > > + final GeneratedExtension > extension, + final int index) { + return internalGetResult().getExtension(extension, index); + } + + /** Set the value of an extension. */ + public final BuilderType setExtension( + final GeneratedExtension extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + message.extensions.setField(descriptor, + extension.toReflectionType(value)); + return (BuilderType) this; + } + + /** Set the value of one element of a repeated extension. */ + public final BuilderType setExtension( + // osmand fix >> -> > > + final GeneratedExtension > extension, + final int index, final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + message.extensions.setRepeatedField( + descriptor, index, + extension.singularToReflectionType(value)); + return (BuilderType) this; + } + + /** Append a value to a repeated extension. */ + public final BuilderType addExtension( + // osmand fix >> -> > > + final GeneratedExtension > extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + final FieldDescriptor descriptor = extension.getDescriptor(); + message.extensions.addRepeatedField( + descriptor, extension.singularToReflectionType(value)); + return (BuilderType) this; + } + + /** Clear an extension. */ + public final BuilderType clearExtension( + final GeneratedExtension extension) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.clearField(extension.getDescriptor()); + return (BuilderType) this; + } + + /** + * Called by subclasses to parse an unknown field or an extension. + * @return {@code true} unless the tag is an end-group tag. + */ + @Override + protected boolean parseUnknownField( + final CodedInputStream input, + final UnknownFieldSet.Builder unknownFields, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + final ExtendableMessage message = internalGetResult(); + return AbstractMessage.Builder.mergeFieldFrom( + input, unknownFields, extensionRegistry, this, tag); + } + + // --------------------------------------------------------------- + // Reflection + + // We don't have to override the get*() methods here because they already + // just forward to the underlying message. + + @Override + public BuilderType setField(final FieldDescriptor field, + final Object value) { + if (field.isExtension()) { + final ExtendableMessage message = internalGetResult(); + message.verifyContainingType(field); + message.extensions.setField(field, value); + return (BuilderType) this; + } else { + return super.setField(field, value); + } + } + + @Override + public BuilderType clearField(final FieldDescriptor field) { + if (field.isExtension()) { + final ExtendableMessage message = internalGetResult(); + message.verifyContainingType(field); + message.extensions.clearField(field); + return (BuilderType) this; + } else { + return super.clearField(field); + } + } + + @Override + public BuilderType setRepeatedField(final FieldDescriptor field, + final int index, final Object value) { + if (field.isExtension()) { + final ExtendableMessage message = internalGetResult(); + message.verifyContainingType(field); + message.extensions.setRepeatedField(field, index, value); + return (BuilderType) this; + } else { + return super.setRepeatedField(field, index, value); + } + } + + @Override + public BuilderType addRepeatedField(final FieldDescriptor field, + final Object value) { + if (field.isExtension()) { + final ExtendableMessage message = internalGetResult(); + message.verifyContainingType(field); + message.extensions.addRepeatedField(field, value); + return (BuilderType) this; + } else { + return super.addRepeatedField(field, value); + } + } + + protected final void mergeExtensionFields(final ExtendableMessage other) { + internalGetResult().extensions.mergeFrom(other.extensions); + } + } + + // ----------------------------------------------------------------- + + /** For use by generated code only. */ + public static + GeneratedExtension + newGeneratedExtension() { + return new GeneratedExtension(); + } + + /** + * Type used to represent generated extensions. The protocol compiler + * generates a static singleton instance of this class for each extension. + * + *

For example, imagine you have the {@code .proto} file: + * + *

+   * option java_class = "MyProto";
+   *
+   * message Foo {
+   *   extensions 1000 to max;
+   * }
+   *
+   * extend Foo {
+   *   optional int32 bar;
+   * }
+   * 
+ * + *

Then, {@code MyProto.Foo.bar} has type + * {@code GeneratedExtension}. + * + *

In general, users should ignore the details of this type, and simply use + * these static singletons as parameters to the extension accessors defined + * in {@link ExtendableMessage} and {@link ExtendableBuilder}. + */ + public static final class GeneratedExtension< + ContainingType extends Message, Type> { + // TODO(kenton): Find ways to avoid using Java reflection within this + // class. Also try to avoid suppressing unchecked warnings. + + // We can't always initialize a GeneratedExtension when we first construct + // it due to initialization order difficulties (namely, the descriptor may + // not have been constructed yet, since it is often constructed by the + // initializer of a separate module). So, we construct an uninitialized + // GeneratedExtension once, then call internalInit() on it later. Generated + // code will always call internalInit() on all extensions as part of the + // static initialization code, and internalInit() throws an exception if + // called more than once, so this method is useless to users. + private GeneratedExtension() {} + + /** For use by generated code only. */ + public void internalInit(final FieldDescriptor descriptor, + final Class type) { + if (this.descriptor != null) { + throw new IllegalStateException("Already initialized."); + } + + if (!descriptor.isExtension()) { + throw new IllegalArgumentException( + "GeneratedExtension given a regular (non-extension) field."); + } + + this.descriptor = descriptor; + this.type = type; + + switch (descriptor.getJavaType()) { + case MESSAGE: + enumValueOf = null; + enumGetValueDescriptor = null; + messageDefaultInstance = + (Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"), + null); + if (messageDefaultInstance == null) { + throw new IllegalStateException( + type.getName() + ".getDefaultInstance() returned null."); + } + break; + case ENUM: + enumValueOf = getMethodOrDie(type, "valueOf", + EnumValueDescriptor.class); + enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor"); + messageDefaultInstance = null; + break; + default: + enumValueOf = null; + enumGetValueDescriptor = null; + messageDefaultInstance = null; + break; + } + } + + private FieldDescriptor descriptor; + private Class type; + private Method enumValueOf; + private Method enumGetValueDescriptor; + private Message messageDefaultInstance; + + public FieldDescriptor getDescriptor() { return descriptor; } + + /** + * If the extension is an embedded message or group, returns the default + * instance of the message. + */ + @SuppressWarnings("unchecked") + public Message getMessageDefaultInstance() { + return messageDefaultInstance; + } + + /** + * Convert from the type used by the reflection accessors to the type used + * by native accessors. E.g., for enums, the reflection accessors use + * EnumValueDescriptors but the native accessors use the generated enum + * type. + */ + @SuppressWarnings("unchecked") + private Object fromReflectionType(final Object value) { + if (descriptor.isRepeated()) { + if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || + descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { + // Must convert the whole list. + final List result = new ArrayList(); + for (final Object element : (List) value) { + result.add(singularFromReflectionType(element)); + } + return result; + } else { + return value; + } + } else { + return singularFromReflectionType(value); + } + } + + /** + * Like {@link #fromReflectionType(Object)}, but if the type is a repeated + * type, this converts a single element. + */ + private Object singularFromReflectionType(final Object value) { + switch (descriptor.getJavaType()) { + case MESSAGE: + if (type.isInstance(value)) { + return value; + } else { + // It seems the copy of the embedded message stored inside the + // extended message is not of the exact type the user was + // expecting. This can happen if a user defines a + // GeneratedExtension manually and gives it a different type. + // This should not happen in normal use. But, to be nice, we'll + // copy the message to whatever type the caller was expecting. + return messageDefaultInstance.newBuilderForType() + .mergeFrom((Message) value).build(); + } + case ENUM: + return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); + default: + return value; + } + } + + /** + * Convert from the type used by the native accessors to the type used + * by reflection accessors. E.g., for enums, the reflection accessors use + * EnumValueDescriptors but the native accessors use the generated enum + * type. + */ + @SuppressWarnings("unchecked") + private Object toReflectionType(final Object value) { + if (descriptor.isRepeated()) { + if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { + // Must convert the whole list. + final List result = new ArrayList(); + for (final Object element : (List) value) { + result.add(singularToReflectionType(element)); + } + return result; + } else { + return value; + } + } else { + return singularToReflectionType(value); + } + } + + /** + * Like {@link #toReflectionType(Object)}, but if the type is a repeated + * type, this converts a single element. + */ + private Object singularToReflectionType(final Object value) { + switch (descriptor.getJavaType()) { + case ENUM: + return invokeOrDie(enumGetValueDescriptor, value); + default: + return value; + } + } + } + + // ================================================================= + + /** Calls Class.getMethod and throws a RuntimeException if it fails. */ + @SuppressWarnings("unchecked") + private static Method getMethodOrDie( + final Class clazz, final String name, final Class... params) { + try { + return clazz.getMethod(name, params); + } catch (NoSuchMethodException e) { + throw new RuntimeException( + "Generated message class \"" + clazz.getName() + + "\" missing method \"" + name + "\".", e); + } + } + + /** Calls invoke and throws a RuntimeException if it fails. */ + private static Object invokeOrDie( + final Method method, final Object object, final Object... params) { + try { + return method.invoke(object, params); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "Couldn't use Java reflection to implement protocol message " + + "reflection.", e); + } catch (InvocationTargetException e) { + final Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException( + "Unexpected exception thrown by generated accessor method.", cause); + } + } + } + + /** + * Users should ignore this class. This class provides the implementation + * with access to the fields of a message object using Java reflection. + */ + public static final class FieldAccessorTable { + + /** + * Construct a FieldAccessorTable for a particular message class. Only + * one FieldAccessorTable should ever be constructed per class. + * + * @param descriptor The type's descriptor. + * @param camelCaseNames The camelcase names of all fields in the message. + * These are used to derive the accessor method names. + * @param messageClass The message type. + * @param builderClass The builder type. + */ + public FieldAccessorTable( + final Descriptor descriptor, + final String[] camelCaseNames, + final Class messageClass, + final Class builderClass) { + this.descriptor = descriptor; + fields = new FieldAccessor[descriptor.getFields().size()]; + + for (int i = 0; i < fields.length; i++) { + final FieldDescriptor field = descriptor.getFields().get(i); + if (field.isRepeated()) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields[i] = new RepeatedMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { + fields[i] = new RepeatedEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else { + fields[i] = new RepeatedFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } + } else { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields[i] = new SingularMessageFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { + fields[i] = new SingularEnumFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } else { + fields[i] = new SingularFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass); + } + } + } + } + + private final Descriptor descriptor; + private final FieldAccessor[] fields; + + /** Get the FieldAccessor for a particular field. */ + private FieldAccessor getField(final FieldDescriptor field) { + if (field.getContainingType() != descriptor) { + throw new IllegalArgumentException( + "FieldDescriptor does not match message type."); + } else if (field.isExtension()) { + // If this type had extensions, it would subclass ExtendableMessage, + // which overrides the reflection interface to handle extensions. + throw new IllegalArgumentException( + "This type does not have extensions."); + } + return fields[field.getIndex()]; + } + + /** + * Abstract interface that provides access to a single field. This is + * implemented differently depending on the field type and cardinality. + */ + private interface FieldAccessor { + Object get(GeneratedMessage message); + void set(Builder builder, Object value); + Object getRepeated(GeneratedMessage message, int index); + void setRepeated(Builder builder, + int index, Object value); + void addRepeated(Builder builder, Object value); + boolean has(GeneratedMessage message); + int getRepeatedCount(GeneratedMessage message); + void clear(Builder builder); + Message.Builder newBuilder(); + } + + // --------------------------------------------------------------- + + private static class SingularFieldAccessor implements FieldAccessor { + SingularFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); + type = getMethod.getReturnType(); + setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); + hasMethod = + getMethodOrDie(messageClass, "has" + camelCaseName); + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + } + + // Note: We use Java reflection to call public methods rather than + // access private fields directly as this avoids runtime security + // checks. + protected final Class type; + protected final Method getMethod; + protected final Method setMethod; + protected final Method hasMethod; + protected final Method clearMethod; + + @Override + public Object get(final GeneratedMessage message) { + return invokeOrDie(getMethod, message); + } + @Override + public void set(final Builder builder, final Object value) { + invokeOrDie(setMethod, builder, value); + } + @Override + public Object getRepeated(final GeneratedMessage message, + final int index) { + throw new UnsupportedOperationException( + "getRepeatedField() called on a singular field."); + } + @Override + public void setRepeated(final Builder builder, + final int index, final Object value) { + throw new UnsupportedOperationException( + "setRepeatedField() called on a singular field."); + } + @Override + public void addRepeated(final Builder builder, final Object value) { + throw new UnsupportedOperationException( + "addRepeatedField() called on a singular field."); + } + @Override + public boolean has(final GeneratedMessage message) { + return (Boolean) invokeOrDie(hasMethod, message); + } + @Override + public int getRepeatedCount(final GeneratedMessage message) { + throw new UnsupportedOperationException( + "getRepeatedFieldSize() called on a singular field."); + } + @Override + public void clear(final Builder builder) { + invokeOrDie(clearMethod, builder); + } + @Override + public Message.Builder newBuilder() { + throw new UnsupportedOperationException( + "newBuilderForField() called on a non-Message type."); + } + } + + private static class RepeatedFieldAccessor implements FieldAccessor { + RepeatedFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + getMethod = getMethodOrDie(messageClass, + "get" + camelCaseName + "List"); + + getRepeatedMethod = + getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); + type = getRepeatedMethod.getReturnType(); + setRepeatedMethod = + getMethodOrDie(builderClass, "set" + camelCaseName, + Integer.TYPE, type); + addRepeatedMethod = + getMethodOrDie(builderClass, "add" + camelCaseName, type); + getCountMethod = + getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); + + clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + } + + protected final Class type; + protected final Method getMethod; + protected final Method getRepeatedMethod; + protected final Method setRepeatedMethod; + protected final Method addRepeatedMethod; + protected final Method getCountMethod; + protected final Method clearMethod; + + @Override + public Object get(final GeneratedMessage message) { + return invokeOrDie(getMethod, message); + } + @Override + public void set(final Builder builder, final Object value) { + // Add all the elements individually. This serves two purposes: + // 1) Verifies that each element has the correct type. + // 2) Insures that the caller cannot modify the list later on and + // have the modifications be reflected in the message. + clear(builder); + for (final Object element : (List) value) { + addRepeated(builder, element); + } + } + @Override + public Object getRepeated(final GeneratedMessage message, + final int index) { + return invokeOrDie(getRepeatedMethod, message, index); + } + @Override + public void setRepeated(final Builder builder, + final int index, final Object value) { + invokeOrDie(setRepeatedMethod, builder, index, value); + } + @Override + public void addRepeated(final Builder builder, final Object value) { + invokeOrDie(addRepeatedMethod, builder, value); + } + @Override + public boolean has(final GeneratedMessage message) { + throw new UnsupportedOperationException( + "hasField() called on a singular field."); + } + @Override + public int getRepeatedCount(final GeneratedMessage message) { + return (Integer) invokeOrDie(getCountMethod, message); + } + @Override + public void clear(final Builder builder) { + invokeOrDie(clearMethod, builder); + } + @Override + public Message.Builder newBuilder() { + throw new UnsupportedOperationException( + "newBuilderForField() called on a non-Message type."); + } + } + + // --------------------------------------------------------------- + + private static final class SingularEnumFieldAccessor + extends SingularFieldAccessor { + SingularEnumFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + super(descriptor, camelCaseName, messageClass, builderClass); + + valueOfMethod = getMethodOrDie(type, "valueOf", + EnumValueDescriptor.class); + getValueDescriptorMethod = + getMethodOrDie(type, "getValueDescriptor"); + } + + private Method valueOfMethod; + private Method getValueDescriptorMethod; + + @Override + public Object get(final GeneratedMessage message) { + return invokeOrDie(getValueDescriptorMethod, super.get(message)); + } + @Override + public void set(final Builder builder, final Object value) { + super.set(builder, invokeOrDie(valueOfMethod, null, value)); + } + } + + private static final class RepeatedEnumFieldAccessor + extends RepeatedFieldAccessor { + RepeatedEnumFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + super(descriptor, camelCaseName, messageClass, builderClass); + + valueOfMethod = getMethodOrDie(type, "valueOf", + EnumValueDescriptor.class); + getValueDescriptorMethod = + getMethodOrDie(type, "getValueDescriptor"); + } + + private final Method valueOfMethod; + private final Method getValueDescriptorMethod; + + @Override + @SuppressWarnings("unchecked") + public Object get(final GeneratedMessage message) { + final List newList = new ArrayList(); + for (final Object element : (List) super.get(message)) { + newList.add(invokeOrDie(getValueDescriptorMethod, element)); + } + return Collections.unmodifiableList(newList); + } + @Override + public Object getRepeated(final GeneratedMessage message, + final int index) { + return invokeOrDie(getValueDescriptorMethod, + super.getRepeated(message, index)); + } + @Override + public void setRepeated(final Builder builder, + final int index, final Object value) { + super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, + value)); + } + @Override + public void addRepeated(final Builder builder, final Object value) { + super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); + } + } + + // --------------------------------------------------------------- + + private static final class SingularMessageFieldAccessor + extends SingularFieldAccessor { + SingularMessageFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + super(descriptor, camelCaseName, messageClass, builderClass); + + newBuilderMethod = getMethodOrDie(type, "newBuilder"); + } + + private final Method newBuilderMethod; + + private Object coerceType(final Object value) { + if (type.isInstance(value)) { + return value; + } else { + // The value is not the exact right message type. However, if it + // is an alternative implementation of the same type -- e.g. a + // DynamicMessage -- we should accept it. In this case we can make + // a copy of the message. + return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) + .mergeFrom((Message) value).build(); + } + } + + @Override + public void set(final Builder builder, final Object value) { + super.set(builder, coerceType(value)); + } + @Override + public Message.Builder newBuilder() { + return (Message.Builder) invokeOrDie(newBuilderMethod, null); + } + } + + private static final class RepeatedMessageFieldAccessor + extends RepeatedFieldAccessor { + RepeatedMessageFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass) { + super(descriptor, camelCaseName, messageClass, builderClass); + + newBuilderMethod = getMethodOrDie(type, "newBuilder"); + } + + private final Method newBuilderMethod; + + private Object coerceType(final Object value) { + if (type.isInstance(value)) { + return value; + } else { + // The value is not the exact right message type. However, if it + // is an alternative implementation of the same type -- e.g. a + // DynamicMessage -- we should accept it. In this case we can make + // a copy of the message. + return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) + .mergeFrom((Message) value).build(); + } + } + + @Override + public void setRepeated(final Builder builder, + final int index, final Object value) { + super.setRepeated(builder, index, coerceType(value)); + } + @Override + public void addRepeated(final Builder builder, final Object value) { + super.addRepeated(builder, coerceType(value)); + } + @Override + public Message.Builder newBuilder() { + return (Message.Builder) invokeOrDie(newBuilderMethod, null); + } + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/GeneratedMessageLite.java b/OsmAnd-java/src/com/google/protobuf/GeneratedMessageLite.java new file mode 100644 index 0000000000..a5137665c9 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/GeneratedMessageLite.java @@ -0,0 +1,576 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Lite version of {@link GeneratedMessage}. + * + * @author kenton@google.com Kenton Varda + */ +public abstract class GeneratedMessageLite extends AbstractMessageLite { + protected GeneratedMessageLite() {} + + @SuppressWarnings("unchecked") + public abstract static class Builder + extends AbstractMessageLite.Builder { + protected Builder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + /** All subclasses implement this. */ + public abstract BuilderType mergeFrom(MessageType message); + + // Defined here for return type covariance. + @Override + public abstract MessageType getDefaultInstanceForType(); + + /** + * Get the message being built. We don't just pass this to the + * constructor because it becomes null when build() is called. + */ + protected abstract MessageType internalGetResult(); + + /** + * Called by subclasses to parse an unknown field. + * @return {@code true} unless the tag is an end-group tag. + */ + protected boolean parseUnknownField( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + return input.skipField(tag); + } + } + + // ================================================================= + // Extensions-related stuff + + /** + * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. + */ + public abstract static class ExtendableMessage< + MessageType extends ExtendableMessage> + extends GeneratedMessageLite { + protected ExtendableMessage() {} + private final FieldSet extensions = + FieldSet.newFieldSet(); + + private void verifyExtensionContainingType( + final GeneratedExtension extension) { + if (extension.getContainingTypeDefaultInstance() != + getDefaultInstanceForType()) { + // This can only happen if someone uses unchecked operations. + throw new IllegalArgumentException( + "This extension is for a different message type. Please make " + + "sure that you are not suppressing any generics type warnings."); + } + } + + /** Check if a singular extension is present. */ + public final boolean hasExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + return extensions.hasField(extension.descriptor); + } + + /** Get the number of elements in a repeated extension. */ + public final int getExtensionCount( + final GeneratedExtension> extension) { + verifyExtensionContainingType(extension); + return extensions.getRepeatedFieldCount(extension.descriptor); + } + + /** Get the value of an extension. */ + @SuppressWarnings("unchecked") + public final Type getExtension( + final GeneratedExtension extension) { + verifyExtensionContainingType(extension); + final Object value = extensions.getField(extension.descriptor); + if (value == null) { + return extension.defaultValue; + } else { + return (Type) value; + } + } + + /** Get one element of a repeated extension. */ + @SuppressWarnings("unchecked") + public final Type getExtension( + final GeneratedExtension> extension, + final int index) { + verifyExtensionContainingType(extension); + return (Type) extensions.getRepeatedField(extension.descriptor, index); + } + + /** Called by subclasses to check if all extensions are initialized. */ + protected boolean extensionsAreInitialized() { + return extensions.isInitialized(); + } + + /** + * Used by subclasses to serialize extensions. Extension ranges may be + * interleaved with field numbers, but we must write them in canonical + * (sorted by field number) order. ExtensionWriter helps us write + * individual ranges of extensions at once. + */ + protected class ExtensionWriter { + // Imagine how much simpler this code would be if Java iterators had + // a way to get the next element without advancing the iterator. + + private final Iterator> iter = + extensions.iterator(); + private Map.Entry next; + private final boolean messageSetWireFormat; + + private ExtensionWriter(boolean messageSetWireFormat) { + if (iter.hasNext()) { + next = iter.next(); + } + this.messageSetWireFormat = messageSetWireFormat; + } + + public void writeUntil(final int end, final CodedOutputStream output) + throws IOException { + while (next != null && next.getKey().getNumber() < end) { + ExtensionDescriptor extension = next.getKey(); + if (messageSetWireFormat && extension.getLiteJavaType() == + WireFormat.JavaType.MESSAGE && + !extension.isRepeated()) { + output.writeMessageSetExtension(extension.getNumber(), + (MessageLite) next.getValue()); + } else { + FieldSet.writeField(extension, next.getValue(), output); + } + if (iter.hasNext()) { + next = iter.next(); + } else { + next = null; + } + } + } + } + + protected ExtensionWriter newExtensionWriter() { + return new ExtensionWriter(false); + } + protected ExtensionWriter newMessageSetExtensionWriter() { + return new ExtensionWriter(true); + } + + /** Called by subclasses to compute the size of extensions. */ + protected int extensionsSerializedSize() { + return extensions.getSerializedSize(); + } + protected int extensionsSerializedSizeAsMessageSet() { + return extensions.getMessageSetSerializedSize(); + } + } + + /** + * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. + */ + @SuppressWarnings("unchecked") + public abstract static class ExtendableBuilder< + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends Builder { + protected ExtendableBuilder() {} + + // This is implemented here only to work around an apparent bug in the + // Java compiler and/or build system. See bug #1898463. The mere presence + // of this dummy clone() implementation makes it go away. + @Override + public BuilderType clone() { + throw new UnsupportedOperationException( + "This is supposed to be overridden by subclasses."); + } + + @Override + protected abstract MessageType internalGetResult(); + + /** Check if a singular extension is present. */ + public final boolean hasExtension( + final GeneratedExtension extension) { + return internalGetResult().hasExtension(extension); + } + + /** Get the number of elements in a repeated extension. */ + public final int getExtensionCount( + final GeneratedExtension> extension) { + return internalGetResult().getExtensionCount(extension); + } + + /** Get the value of an extension. */ + public final Type getExtension( + final GeneratedExtension extension) { + return internalGetResult().getExtension(extension); + } + + /** Get one element of a repeated extension. */ + public final Type getExtension( + final GeneratedExtension> extension, + final int index) { + return internalGetResult().getExtension(extension, index); + } + + /** Set the value of an extension. */ + public final BuilderType setExtension( + final GeneratedExtension extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.setField(extension.descriptor, value); + return (BuilderType) this; + } + + /** Set the value of one element of a repeated extension. */ + public final BuilderType setExtension( + final GeneratedExtension> extension, + final int index, final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.setRepeatedField(extension.descriptor, index, value); + return (BuilderType) this; + } + + /** Append a value to a repeated extension. */ + public final BuilderType addExtension( + final GeneratedExtension> extension, + final Type value) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.addRepeatedField(extension.descriptor, value); + return (BuilderType) this; + } + + /** Clear an extension. */ + public final BuilderType clearExtension( + final GeneratedExtension extension) { + final ExtendableMessage message = internalGetResult(); + message.verifyExtensionContainingType(extension); + message.extensions.clearField(extension.descriptor); + return (BuilderType) this; + } + + /** + * Called by subclasses to parse an unknown field or an extension. + * @return {@code true} unless the tag is an end-group tag. + */ + @Override + protected boolean parseUnknownField( + final CodedInputStream input, + final ExtensionRegistryLite extensionRegistry, + final int tag) throws IOException { + final FieldSet extensions = + ((ExtendableMessage) internalGetResult()).extensions; + + final int wireType = WireFormat.getTagWireType(tag); + final int fieldNumber = WireFormat.getTagFieldNumber(tag); + + final GeneratedExtension extension = + extensionRegistry.findLiteExtensionByNumber( + getDefaultInstanceForType(), fieldNumber); + + boolean unknown = false; + boolean packed = false; + if (extension == null) { + unknown = true; // Unknown field. + } else if (wireType == FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), + false /* isPacked */)) { + packed = false; // Normal, unpacked value. + } else if (extension.descriptor.isRepeated && + extension.descriptor.type.isPackable() && + wireType == FieldSet.getWireFormatForFieldType( + extension.descriptor.getLiteType(), + true /* isPacked */)) { + packed = true; // Packed value. + } else { + unknown = true; // Wrong wire type. + } + + if (unknown) { // Unknown field or wrong wire type. Skip. + return input.skipField(tag); + } + + if (packed) { + final int length = input.readRawVarint32(); + final int limit = input.pushLimit(length); + if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { + while (input.getBytesUntilLimit() > 0) { + final int rawValue = input.readEnum(); + final Object value = + extension.descriptor.getEnumType().findValueByNumber(rawValue); + if (value == null) { + // If the number isn't recognized as a valid value for this + // enum, drop it (don't even add it to unknownFields). + return true; + } + extensions.addRepeatedField(extension.descriptor, value); + } + } else { + while (input.getBytesUntilLimit() > 0) { + final Object value = + FieldSet.readPrimitiveField(input, + extension.descriptor.getLiteType()); + extensions.addRepeatedField(extension.descriptor, value); + } + } + input.popLimit(limit); + } else { + final Object value; + switch (extension.descriptor.getLiteJavaType()) { + case MESSAGE: { + MessageLite.Builder subBuilder = null; + if (!extension.descriptor.isRepeated()) { + MessageLite existingValue = + (MessageLite) extensions.getField(extension.descriptor); + if (existingValue != null) { + subBuilder = existingValue.toBuilder(); + } + } + if (subBuilder == null) { + subBuilder = extension.messageDefaultInstance.newBuilderForType(); + } + if (extension.descriptor.getLiteType() == + WireFormat.FieldType.GROUP) { + input.readGroup(extension.getNumber(), + subBuilder, extensionRegistry); + } else { + input.readMessage(subBuilder, extensionRegistry); + } + value = subBuilder.build(); + break; + } + case ENUM: + final int rawValue = input.readEnum(); + value = extension.descriptor.getEnumType() + .findValueByNumber(rawValue); + // If the number isn't recognized as a valid value for this enum, + // drop it. + if (value == null) { + return true; + } + break; + default: + value = FieldSet.readPrimitiveField(input, + extension.descriptor.getLiteType()); + break; + } + + if (extension.descriptor.isRepeated()) { + extensions.addRepeatedField(extension.descriptor, value); + } else { + extensions.setField(extension.descriptor, value); + } + } + + return true; + } + + protected final void mergeExtensionFields(final MessageType other) { + ((ExtendableMessage) internalGetResult()).extensions.mergeFrom( + ((ExtendableMessage) other).extensions); + } + } + + // ----------------------------------------------------------------- + + /** For use by generated code only. */ + public static + GeneratedExtension + newGeneratedExtension() { + return new GeneratedExtension(); + } + + private static final class ExtensionDescriptor + implements FieldSet.FieldDescriptorLite< + ExtensionDescriptor> { + private ExtensionDescriptor( + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final boolean isRepeated, + final boolean isPacked) { + this.enumTypeMap = enumTypeMap; + this.number = number; + this.type = type; + this.isRepeated = isRepeated; + this.isPacked = isPacked; + } + + private final Internal.EnumLiteMap enumTypeMap; + private final int number; + private final WireFormat.FieldType type; + private final boolean isRepeated; + private final boolean isPacked; + + @Override + public int getNumber() { + return number; + } + + @Override + public WireFormat.FieldType getLiteType() { + return type; + } + + @Override + public WireFormat.JavaType getLiteJavaType() { + return type.getJavaType(); + } + + @Override + public boolean isRepeated() { + return isRepeated; + } + + @Override + public boolean isPacked() { + return isPacked; + } + + @Override + public Internal.EnumLiteMap getEnumType() { + return enumTypeMap; + } + + @Override + @SuppressWarnings("unchecked") + public MessageLite.Builder internalMergeFrom( + MessageLite.Builder to, MessageLite from) { + return ((Builder) to).mergeFrom((GeneratedMessageLite) from); + } + + @Override + public int compareTo(ExtensionDescriptor other) { + return number - other.number; + } + } + + /** + * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}. + * + * Users should ignore the contents of this class and only use objects of + * this type as parameters to extension accessors and ExtensionRegistry.add(). + */ + public static final class GeneratedExtension< + ContainingType extends MessageLite, Type> { + // We can't always initialize a GeneratedExtension when we first construct + // it due to initialization order difficulties (namely, the default + // instances may not have been constructed yet). So, we construct an + // uninitialized GeneratedExtension once, then call internalInit() on it + // later. Generated code will always call internalInit() on all extensions + // as part of the static initialization code, and internalInit() throws an + // exception if called more than once, so this method is useless to users. + private GeneratedExtension() {} + + private void internalInit( + final ContainingType containingTypeDefaultInstance, + final Type defaultValue, + final MessageLite messageDefaultInstance, + final ExtensionDescriptor descriptor) { + this.containingTypeDefaultInstance = containingTypeDefaultInstance; + this.defaultValue = defaultValue; + this.messageDefaultInstance = messageDefaultInstance; + this.descriptor = descriptor; + } + + /** For use by generated code only. */ + public void internalInitSingular( + final ContainingType containingTypeDefaultInstance, + final Type defaultValue, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type) { + internalInit( + containingTypeDefaultInstance, defaultValue, messageDefaultInstance, + new ExtensionDescriptor(enumTypeMap, number, type, + false /* isRepeated */, false /* isPacked */)); + } + + /** For use by generated code only. */ + @SuppressWarnings("unchecked") + public void internalInitRepeated( + final ContainingType containingTypeDefaultInstance, + final MessageLite messageDefaultInstance, + final Internal.EnumLiteMap enumTypeMap, + final int number, + final WireFormat.FieldType type, + final boolean isPacked) { + internalInit( + containingTypeDefaultInstance, (Type) Collections.emptyList(), + messageDefaultInstance, + new ExtensionDescriptor( + enumTypeMap, number, type, true /* isRepeated */, isPacked)); + } + + private ContainingType containingTypeDefaultInstance; + private Type defaultValue; + private MessageLite messageDefaultInstance; + private ExtensionDescriptor descriptor; + + /** + * Default instance of the type being extended, used to identify that type. + */ + public ContainingType getContainingTypeDefaultInstance() { + return containingTypeDefaultInstance; + } + + /** Get the field number. */ + public int getNumber() { + return descriptor.getNumber(); + } + + /** + * If the extension is an embedded message, this is the default instance of + * that type. + */ + public MessageLite getMessageDefaultInstance() { + return messageDefaultInstance; + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/Internal.java b/OsmAnd-java/src/com/google/protobuf/Internal.java new file mode 100644 index 0000000000..965465e14b --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/Internal.java @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.UnsupportedEncodingException; + +/** + * The classes contained within are used internally by the Protocol Buffer + * library and generated message implementations. They are public only because + * those generated messages do not reside in the {@code protobuf} package. + * Others should not use this class directly. + * + * @author kenton@google.com (Kenton Varda) + */ +public class Internal { + /** + * Helper called by generated code to construct default values for string + * fields. + *

+ * The protocol compiler does not actually contain a UTF-8 decoder -- it + * just pushes UTF-8-encoded text around without touching it. The one place + * where this presents a problem is when generating Java string literals. + * Unicode characters in the string literal would normally need to be encoded + * using a Unicode escape sequence, which would require decoding them. + * To get around this, protoc instead embeds the UTF-8 bytes into the + * generated code and leaves it to the runtime library to decode them. + *

+ * It gets worse, though. If protoc just generated a byte array, like: + * new byte[] {0x12, 0x34, 0x56, 0x78} + * Java actually generates *code* which allocates an array and then fills + * in each value. This is much less efficient than just embedding the bytes + * directly into the bytecode. To get around this, we need another + * work-around. String literals are embedded directly, so protoc actually + * generates a string literal corresponding to the bytes. The easiest way + * to do this is to use the ISO-8859-1 character set, which corresponds to + * the first 256 characters of the Unicode range. Protoc can then use + * good old CEscape to generate the string. + *

+ * So we have a string literal which represents a set of bytes which + * represents another string. This function -- stringDefaultValue -- + * converts from the generated string to the string we actually want. The + * generated code calls this automatically. + */ + public static String stringDefaultValue(String bytes) { + try { + return new String(bytes.getBytes("ISO-8859-1"), "UTF-8"); + } catch (UnsupportedEncodingException e) { + // This should never happen since all JVMs are required to implement + // both of the above character sets. + throw new IllegalStateException( + "Java VM does not support a standard character set.", e); + } + } + + /** + * Helper called by generated code to construct default values for bytes + * fields. + *

+ * This is a lot like {@link #stringDefaultValue}, but for bytes fields. + * In this case we only need the second of the two hacks -- allowing us to + * embed raw bytes as a string literal with ISO-8859-1 encoding. + */ + public static ByteString bytesDefaultValue(String bytes) { + try { + return ByteString.copyFrom(bytes.getBytes("ISO-8859-1")); + } catch (UnsupportedEncodingException e) { + // This should never happen since all JVMs are required to implement + // ISO-8859-1. + throw new IllegalStateException( + "Java VM does not support a standard character set.", e); + } + } + + /** + * Interface for an enum value or value descriptor, to be used in FieldSet. + * The lite library stores enum values directly in FieldSets but the full + * library stores EnumValueDescriptors in order to better support reflection. + */ + public interface EnumLite { + int getNumber(); + } + + /** + * Interface for an object which maps integers to {@link EnumLite}s. + * {@link Descriptors.EnumDescriptor} implements this interface by mapping + * numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally, + * every generated enum type has a static method internalGetValueMap() which + * returns an implementation of this type that maps numbers to enum values. + */ + public interface EnumLiteMap { + T findValueByNumber(int number); + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/InvalidProtocolBufferException.java b/OsmAnd-java/src/com/google/protobuf/InvalidProtocolBufferException.java new file mode 100644 index 0000000000..90f7ffbc28 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/InvalidProtocolBufferException.java @@ -0,0 +1,93 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; + +/** + * Thrown when a protocol message being parsed is invalid in some way, + * e.g. it contains a malformed varint or a negative byte length. + * + * @author kenton@google.com Kenton Varda + */ +public class InvalidProtocolBufferException extends IOException { + private static final long serialVersionUID = -1616151763072450476L; + + public InvalidProtocolBufferException(final String description) { + super(description); + } + + static InvalidProtocolBufferException truncatedMessage() { + return new InvalidProtocolBufferException( + "While parsing a protocol message, the input ended unexpectedly " + + "in the middle of a field. This could mean either than the " + + "input has been truncated or that an embedded message " + + "misreported its own length."); + } + + static InvalidProtocolBufferException negativeSize() { + return new InvalidProtocolBufferException( + "CodedInputStream encountered an embedded string or message " + + "which claimed to have negative size."); + } + + static InvalidProtocolBufferException malformedVarint() { + return new InvalidProtocolBufferException( + "CodedInputStream encountered a malformed varint."); + } + + static InvalidProtocolBufferException invalidTag() { + return new InvalidProtocolBufferException( + "Protocol message contained an invalid tag (zero)."); + } + + static InvalidProtocolBufferException invalidEndTag() { + return new InvalidProtocolBufferException( + "Protocol message end-group tag did not match expected tag."); + } + + static InvalidProtocolBufferException invalidWireType() { + return new InvalidProtocolBufferException( + "Protocol message tag had invalid wire type."); + } + + static InvalidProtocolBufferException recursionLimitExceeded() { + return new InvalidProtocolBufferException( + "Protocol message had too many levels of nesting. May be malicious. " + + "Use CodedInputStream.setRecursionLimit() to increase the depth limit."); + } + + static InvalidProtocolBufferException sizeLimitExceeded() { + return new InvalidProtocolBufferException( + "Protocol message was too large. May be malicious. " + + "Use CodedInputStream.setSizeLimit() to increase the size limit."); + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/Message.java b/OsmAnd-java/src/com/google/protobuf/Message.java new file mode 100644 index 0000000000..bd8ed82973 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/Message.java @@ -0,0 +1,325 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// TODO(kenton): Use generics? E.g. Builder, then +// mergeFrom*() could return BuilderType for better type-safety. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +/** + * Abstract interface implemented by Protocol Message objects. + *

+ * See also {@link MessageLite}, which defines most of the methods that typical + * users care about. {@link Message} adds to it methods that are not available + * in the "lite" runtime. The biggest added features are introspection and + * reflection -- i.e., getting descriptors for the message type and accessing + * the field values dynamically. + * + * @author kenton@google.com Kenton Varda + */ +public interface Message extends MessageLite { + /** + * Get the message's type's descriptor. This differs from the + * {@code getDescriptor()} method of generated message classes in that + * this method is an abstract method of the {@code Message} interface + * whereas {@code getDescriptor()} is a static method of a specific class. + * They return the same thing. + */ + Descriptors.Descriptor getDescriptorForType(); + + // (From MessageLite, re-declared here only for return type covariance.) + @Override +Message getDefaultInstanceForType(); + + /** + * Returns a collection of all the fields in this message which are set + * and their corresponding values. A singular ("required" or "optional") + * field is set iff hasField() returns true for that field. A "repeated" + * field is set iff getRepeatedFieldSize() is greater than zero. The + * values are exactly what would be returned by calling + * {@link #getField(Descriptors.FieldDescriptor)} for each field. The map + * is guaranteed to be a sorted map, so iterating over it will return fields + * in order by field number. + */ + Map getAllFields(); + + /** + * Returns true if the given field is set. This is exactly equivalent to + * calling the generated "has" accessor method corresponding to the field. + * @throws IllegalArgumentException The field is a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + boolean hasField(Descriptors.FieldDescriptor field); + + /** + * Obtains the value of the given field, or the default value if it is + * not set. For primitive fields, the boxed primitive value is returned. + * For enum fields, the EnumValueDescriptor for the value is returend. For + * embedded message fields, the sub-message is returned. For repeated + * fields, a java.util.List is returned. + */ + Object getField(Descriptors.FieldDescriptor field); + + /** + * Gets the number of elements of a repeated field. This is exactly + * equivalent to calling the generated "Count" accessor method corresponding + * to the field. + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + int getRepeatedFieldCount(Descriptors.FieldDescriptor field); + + /** + * Gets an element of a repeated field. For primitive fields, the boxed + * primitive value is returned. For enum fields, the EnumValueDescriptor + * for the value is returend. For embedded message fields, the sub-message + * is returned. + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + Object getRepeatedField(Descriptors.FieldDescriptor field, int index); + + /** Get the {@link UnknownFieldSet} for this message. */ + UnknownFieldSet getUnknownFields(); + + // ----------------------------------------------------------------- + // Comparison and hashing + + /** + * Compares the specified object with this message for equality. Returns + * true if the given object is a message of the same type (as + * defined by {@code getDescriptorForType()}) and has identical values for + * all of its fields. + * + * @param other object to be compared for equality with this message + * @return true if the specified object is equal to this message + */ + @Override + boolean equals(Object other); + + /** + * Returns the hash code value for this message. The hash code of a message + * is defined to be getDescriptor().hashCode() ^ map.hashCode(), + * where map is a map of field numbers to field values. + * + * @return the hash code value for this message + * @see Map#hashCode() + */ + @Override + int hashCode(); + + // ----------------------------------------------------------------- + // Convenience methods. + + /** + * Converts the message to a string in protocol buffer text format. This is + * just a trivial wrapper around {@link TextFormat#printToString(Message)}. + */ + @Override + String toString(); + + // ================================================================= + // Builders + + // (From MessageLite, re-declared here only for return type covariance.) + @Override +Builder newBuilderForType(); + @Override +Builder toBuilder(); + + /** + * Abstract interface implemented by Protocol Message builders. + */ + interface Builder extends MessageLite.Builder { + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) + @Override + Builder clear(); + + /** + * Merge {@code other} into the message being built. {@code other} must + * have the exact same type as {@code this} (i.e. + * {@code getDescriptorForType() == other.getDescriptorForType()}). + * + * Merging occurs as follows. For each field:
+ * * For singular primitive fields, if the field is set in {@code other}, + * then {@code other}'s value overwrites the value in this message.
+ * * For singular message fields, if the field is set in {@code other}, + * it is merged into the corresponding sub-message of this message + * using the same merging rules.
+ * * For repeated fields, the elements in {@code other} are concatenated + * with the elements in this message. + * + * This is equivalent to the {@code Message::MergeFrom} method in C++. + */ + Builder mergeFrom(Message other); + + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) + @Override + Message build(); + @Override + Message buildPartial(); + @Override + Builder clone(); + @Override + Builder mergeFrom(CodedInputStream input) throws IOException; + @Override + Builder mergeFrom(CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Get the message's type's descriptor. + * See {@link Message#getDescriptorForType()}. + */ + Descriptors.Descriptor getDescriptorForType(); + + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) + @Override + Message getDefaultInstanceForType(); + + /** + * Like {@link Message#getAllFields()}. The returned map may or may not + * reflect future changes to the builder. Either way, the returned map is + * itself unmodifiable. + */ + Map getAllFields(); + + /** + * Create a Builder for messages of the appropriate type for the given + * field. Messages built with this can then be passed to setField(), + * setRepeatedField(), or addRepeatedField(). + */ + Builder newBuilderForField(Descriptors.FieldDescriptor field); + + /** Like {@link Message#hasField(Descriptors.FieldDescriptor)} */ + boolean hasField(Descriptors.FieldDescriptor field); + + /** Like {@link Message#getField(Descriptors.FieldDescriptor)} */ + Object getField(Descriptors.FieldDescriptor field); + + /** + * Sets a field to the given value. The value must be of the correct type + * for this field, i.e. the same type that + * {@link Message#getField(Descriptors.FieldDescriptor)} would return. + */ + Builder setField(Descriptors.FieldDescriptor field, Object value); + + /** + * Clears the field. This is exactly equivalent to calling the generated + * "clear" accessor method corresponding to the field. + */ + Builder clearField(Descriptors.FieldDescriptor field); + + /** + * Like {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)} + */ + int getRepeatedFieldCount(Descriptors.FieldDescriptor field); + + /** + * Like {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} + */ + Object getRepeatedField(Descriptors.FieldDescriptor field, int index); + + /** + * Sets an element of a repeated field to the given value. The value must + * be of the correct type for this field, i.e. the same type that + * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} would + * return. + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + Builder setRepeatedField(Descriptors.FieldDescriptor field, + int index, Object value); + + /** + * Like {@code setRepeatedField}, but appends the value as a new element. + * @throws IllegalArgumentException The field is not a repeated field, or + * {@code field.getContainingType() != getDescriptorForType()}. + */ + Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value); + + /** Get the {@link UnknownFieldSet} for this message. */ + UnknownFieldSet getUnknownFields(); + + /** Set the {@link UnknownFieldSet} for this message. */ + Builder setUnknownFields(UnknownFieldSet unknownFields); + + /** + * Merge some unknown fields into the {@link UnknownFieldSet} for this + * message. + */ + Builder mergeUnknownFields(UnknownFieldSet unknownFields); + + // --------------------------------------------------------------- + // Convenience methods. + + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) + @Override + Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; + @Override + Builder mergeFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + @Override + Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; + @Override + Builder mergeFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException; + @Override + Builder mergeFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + @Override + Builder mergeFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + @Override + Builder mergeFrom(InputStream input) throws IOException; + @Override + Builder mergeFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + @Override + boolean mergeDelimitedFrom(InputStream input) + throws IOException; + @Override + boolean mergeDelimitedFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/MessageLite.java b/OsmAnd-java/src/com/google/protobuf/MessageLite.java new file mode 100644 index 0000000000..cf7f39e2f5 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/MessageLite.java @@ -0,0 +1,335 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// TODO(kenton): Use generics? E.g. Builder, then +// mergeFrom*() could return BuilderType for better type-safety. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Abstract interface implemented by Protocol Message objects. + * + *

This interface is implemented by all protocol message objects. Non-lite + * messages additionally implement the Message interface, which is a subclass + * of MessageLite. Use MessageLite instead when you only need the subset of + * features which it supports -- namely, nothing that uses descriptors or + * reflection. You can instruct the protocol compiler to generate classes + * which implement only MessageLite, not the full Message interface, by adding + * the follow line to the .proto file: + *

+ *   option optimize_for = LITE_RUNTIME;
+ * 
+ * + *

This is particularly useful on resource-constrained systems where the + * full protocol buffers runtime library is too big. + * + *

Note that on non-constrained systems (e.g. servers) when you need to link + * in lots of protocol definitions, a better way to reduce total code footprint + * is to use {@code optimize_for = CODE_SIZE}. This will make the generated + * code smaller while still supporting all the same features (at the expense of + * speed). {@code optimize_for = LITE_RUNTIME} is best when you only have a + * small number of message types linked into your binary, in which case the + * size of the protocol buffers runtime itself is the biggest problem. + * + * @author kenton@google.com Kenton Varda + */ +public interface MessageLite { + /** + * Get an instance of the type with all fields set to their default values. + * This may or may not be a singleton. This differs from the + * {@code getDefaultInstance()} method of generated message classes in that + * this method is an abstract method of the {@code MessageLite} interface + * whereas {@code getDefaultInstance()} is a static method of a specific + * class. They return the same thing. + */ + MessageLite getDefaultInstanceForType(); + + /** + * Returns true if all required fields in the message and all embedded + * messages are set, false otherwise. + */ + boolean isInitialized(); + + /** + * Serializes the message and writes it to {@code output}. This does not + * flush or close the stream. + */ + void writeTo(CodedOutputStream output) throws IOException; + + /** + * Get the number of bytes required to encode this message. The result + * is only computed on the first call and memoized after that. + */ + int getSerializedSize(); + + // ----------------------------------------------------------------- + // Convenience methods. + + /** + * Serializes the message to a {@code ByteString} and returns it. This is + * just a trivial wrapper around + * {@link #writeTo(CodedOutputStream)}. + */ + ByteString toByteString(); + + /** + * Serializes the message to a {@code byte} array and returns it. This is + * just a trivial wrapper around + * {@link #writeTo(CodedOutputStream)}. + */ + byte[] toByteArray(); + + /** + * Serializes the message and writes it to {@code output}. This is just a + * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does + * not flush or close the stream. + *

+ * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write + * any more data to the stream after the message, you must somehow ensure + * that the parser on the receiving end does not interpret this as being + * part of the protocol message. This can be done e.g. by writing the size + * of the message before the data, then making sure to limit the input to + * that size on the receiving end (e.g. by wrapping the InputStream in one + * which limits the input). Alternatively, just use + * {@link #writeDelimitedTo(OutputStream)}. + */ + void writeTo(OutputStream output) throws IOException; + + /** + * Like {@link #writeTo(OutputStream)}, but writes the size of the message + * as a varint before writing the data. This allows more data to be written + * to the stream after the message without the need to delimit the message + * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or + * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)}) + * to parse messages written by this method. + */ + void writeDelimitedTo(OutputStream output) throws IOException; + + // ================================================================= + // Builders + + /** + * Constructs a new builder for a message of the same type as this message. + */ + Builder newBuilderForType(); + + /** + * Constructs a builder initialized with the current message. Use this to + * derive a new message from the current one. + */ + Builder toBuilder(); + + /** + * Abstract interface implemented by Protocol Message builders. + */ + interface Builder extends Cloneable { + /** Resets all fields to their default values. */ + Builder clear(); + + /** + * Construct the final message. Once this is called, the Builder is no + * longer valid, and calling any other method will result in undefined + * behavior and may throw a NullPointerException. If you need to continue + * working with the builder after calling {@code build()}, {@code clone()} + * it first. + * @throws UninitializedMessageException The message is missing one or more + * required fields (i.e. {@link #isInitialized()} returns false). + * Use {@link #buildPartial()} to bypass this check. + */ + MessageLite build(); + + /** + * Like {@link #build()}, but does not throw an exception if the message + * is missing required fields. Instead, a partial message is returned. + * Once this is called, the Builder is no longer valid, and calling any + * will result in undefined behavior and may throw a NullPointerException. + * + * If you need to continue working with the builder after calling + * {@code buildPartial()}, {@code clone()} it first. + */ + MessageLite buildPartial(); + + /** + * Clones the Builder. + * @see Object#clone() + */ + Builder clone(); + + /** + * Returns true if all required fields in the message and all embedded + * messages are set, false otherwise. + */ + boolean isInitialized(); + + /** + * Parses a message of this type from the input and merges it with this + * message, as if using {@link Builder#mergeFrom(MessageLite)}. + * + *

Warning: This does not verify that all required fields are present in + * the input message. If you call {@link #build()} without setting all + * required fields, it will throw an {@link UninitializedMessageException}, + * which is a {@code RuntimeException} and thus might not be caught. There + * are a few good ways to deal with this: + *

    + *
  • Call {@link #isInitialized()} to verify that all required fields + * are set before building. + *
  • Parse the message separately using one of the static + * {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)} + * to merge it with this one. {@code parseFrom} will throw an + * {@link InvalidProtocolBufferException} (an {@code IOException}) + * if some required fields are missing. + *
  • Use {@code buildPartial()} to build, which ignores missing + * required fields. + *
+ * + *

Note: The caller should call + * {@link CodedInputStream#checkLastTagWas(int)} after calling this to + * verify that the last tag seen was the appropriate end-group tag, + * or zero for EOF. + */ + Builder mergeFrom(CodedInputStream input) throws IOException; + + /** + * Like {@link Builder#mergeFrom(CodedInputStream)}, but also + * parses extensions. The extensions that you want to be able to parse + * must be registered in {@code extensionRegistry}. Extensions not in + * the registry will be treated as unknown fields. + */ + Builder mergeFrom(CodedInputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Get the message's type's default instance. + * See {@link MessageLite#getDefaultInstanceForType()}. + */ + MessageLite getDefaultInstanceForType(); + + // --------------------------------------------------------------- + // Convenience methods. + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + Builder mergeFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + /** + * Parse a message of this type from {@code input} and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. Note that this method always + * reads the entire input (unless it throws an exception). If you + * want it to stop earlier, you will need to wrap your input in some + * wrapper stream that limits reading. Or, use + * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message + * and {@link #mergeDelimitedFrom(InputStream)} to read it. + *

+ * Despite usually reading the entire input, this does not close the stream. + */ + Builder mergeFrom(InputStream input) throws IOException; + + /** + * Parse a message of this type from {@code input} and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + + /** + * Like {@link #mergeFrom(InputStream)}, but does not read until EOF. + * Instead, the size of the message (encoded as a varint) is read first, + * then the message data. Use + * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in + * this format. + * + * @returns True if successful, or false if the stream is at EOF when the + * method starts. Any other error (including reaching EOF during + * parsing) will cause an exception to be thrown. + */ + boolean mergeDelimitedFrom(InputStream input) + throws IOException; + + /** + * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions. + */ + boolean mergeDelimitedFrom(InputStream input, + ExtensionRegistryLite extensionRegistry) + throws IOException; + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/ProtocolMessageEnum.java b/OsmAnd-java/src/com/google/protobuf/ProtocolMessageEnum.java new file mode 100644 index 0000000000..f25cd3d908 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/ProtocolMessageEnum.java @@ -0,0 +1,59 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import com.google.protobuf.Descriptors.EnumDescriptor; +import com.google.protobuf.Descriptors.EnumValueDescriptor; + +/** + * Interface of useful methods added to all enums generated by the protocol + * compiler. + */ +public interface ProtocolMessageEnum extends Internal.EnumLite { + + /** + * Return the value's numeric value as defined in the .proto file. + */ + @Override +int getNumber(); + + /** + * Return the value's descriptor, which contains information such as + * value name, number, and type. + */ + EnumValueDescriptor getValueDescriptor(); + + /** + * Return the enum type's descriptor, which contains information + * about each defined value, etc. + */ + EnumDescriptor getDescriptorForType(); +} diff --git a/OsmAnd-java/src/com/google/protobuf/RpcCallback.java b/OsmAnd-java/src/com/google/protobuf/RpcCallback.java new file mode 100644 index 0000000000..1fd35ed332 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/RpcCallback.java @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * Interface for an RPC callback, normally called when an RPC completes. + * {@code ParameterType} is normally the method's response message type. + * + *

Starting with version 2.3.0, RPC implementations should not try to build + * on this, but should instead provide code generator plugins which generate + * code specific to the particular RPC implementation. This way the generated + * code can be more appropriate for the implementation in use and can avoid + * unnecessary layers of indirection. + * + * @author kenton@google.com Kenton Varda + */ +public interface RpcCallback { + void run(ParameterType parameter); +} diff --git a/OsmAnd-java/src/com/google/protobuf/RpcChannel.java b/OsmAnd-java/src/com/google/protobuf/RpcChannel.java new file mode 100644 index 0000000000..c6ec54fc91 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/RpcChannel.java @@ -0,0 +1,71 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + *

Abstract interface for an RPC channel. An {@code RpcChannel} represents a + * communication line to a {@link Service} which can be used to call that + * {@link Service}'s methods. The {@link Service} may be running on another + * machine. Normally, you should not call an {@code RpcChannel} directly, but + * instead construct a stub {@link Service} wrapping it. Example: + * + *

+ *   RpcChannel channel = rpcImpl.newChannel("remotehost.example.com:1234");
+ *   RpcController controller = rpcImpl.newController();
+ *   MyService service = MyService.newStub(channel);
+ *   service.myMethod(controller, request, callback);
+ * 
+ * + *

Starting with version 2.3.0, RPC implementations should not try to build + * on this, but should instead provide code generator plugins which generate + * code specific to the particular RPC implementation. This way the generated + * code can be more appropriate for the implementation in use and can avoid + * unnecessary layers of indirection. + * + * @author kenton@google.com Kenton Varda + */ +public interface RpcChannel { + /** + * Call the given method of the remote service. This method is similar to + * {@code Service.callMethod()} with one important difference: the caller + * decides the types of the {@code Message} objects, not the callee. The + * request may be of any type as long as + * {@code request.getDescriptor() == method.getInputType()}. + * The response passed to the callback will be of the same type as + * {@code responsePrototype} (which must have + * {@code getDescriptor() == method.getOutputType()}). + */ + void callMethod(Descriptors.MethodDescriptor method, + RpcController controller, + Message request, + Message responsePrototype, + RpcCallback done); +} diff --git a/OsmAnd-java/src/com/google/protobuf/RpcController.java b/OsmAnd-java/src/com/google/protobuf/RpcController.java new file mode 100644 index 0000000000..aaa5446da8 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/RpcController.java @@ -0,0 +1,118 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + *

An {@code RpcController} mediates a single method call. The primary + * purpose of the controller is to provide a way to manipulate settings + * specific to the RPC implementation and to find out about RPC-level errors. + * + *

Starting with version 2.3.0, RPC implementations should not try to build + * on this, but should instead provide code generator plugins which generate + * code specific to the particular RPC implementation. This way the generated + * code can be more appropriate for the implementation in use and can avoid + * unnecessary layers of indirection. + * + *

The methods provided by the {@code RpcController} interface are intended + * to be a "least common denominator" set of features which we expect all + * implementations to support. Specific implementations may provide more + * advanced features (e.g. deadline propagation). + * + * @author kenton@google.com Kenton Varda + */ +public interface RpcController { + // ----------------------------------------------------------------- + // These calls may be made from the client side only. Their results + // are undefined on the server side (may throw RuntimeExceptions). + + /** + * Resets the RpcController to its initial state so that it may be reused in + * a new call. This can be called from the client side only. It must not + * be called while an RPC is in progress. + */ + void reset(); + + /** + * After a call has finished, returns true if the call failed. The possible + * reasons for failure depend on the RPC implementation. {@code failed()} + * most only be called on the client side, and must not be called before a + * call has finished. + */ + boolean failed(); + + /** + * If {@code failed()} is {@code true}, returns a human-readable description + * of the error. + */ + String errorText(); + + /** + * Advises the RPC system that the caller desires that the RPC call be + * canceled. The RPC system may cancel it immediately, may wait awhile and + * then cancel it, or may not even cancel the call at all. If the call is + * canceled, the "done" callback will still be called and the RpcController + * will indicate that the call failed at that time. + */ + void startCancel(); + + // ----------------------------------------------------------------- + // These calls may be made from the server side only. Their results + // are undefined on the client side (may throw RuntimeExceptions). + + /** + * Causes {@code failed()} to return true on the client side. {@code reason} + * will be incorporated into the message returned by {@code errorText()}. + * If you find you need to return machine-readable information about + * failures, you should incorporate it into your response protocol buffer + * and should NOT call {@code setFailed()}. + */ + void setFailed(String reason); + + /** + * If {@code true}, indicates that the client canceled the RPC, so the server + * may as well give up on replying to it. This method must be called on the + * server side only. The server should still call the final "done" callback. + */ + boolean isCanceled(); + + /** + * Asks that the given callback be called when the RPC is canceled. The + * parameter passed to the callback will always be {@code null}. The + * callback will always be called exactly once. If the RPC completes without + * being canceled, the callback will be called after completion. If the RPC + * has already been canceled when NotifyOnCancel() is called, the callback + * will be called immediately. + * + *

{@code notifyOnCancel()} must be called no more than once per request. + * It must be called on the server side only. + */ + void notifyOnCancel(RpcCallback callback); +} diff --git a/OsmAnd-java/src/com/google/protobuf/RpcUtil.java b/OsmAnd-java/src/com/google/protobuf/RpcUtil.java new file mode 100644 index 0000000000..202fe1201a --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/RpcUtil.java @@ -0,0 +1,137 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * Grab-bag of utility functions useful when dealing with RPCs. + * + * @author kenton@google.com Kenton Varda + */ +public final class RpcUtil { + private RpcUtil() {} + + /** + * Take an {@code RpcCallback} and convert it to an + * {@code RpcCallback} accepting a specific message type. This is always + * type-safe (parameter type contravariance). + */ + @SuppressWarnings("unchecked") + public static RpcCallback + specializeCallback(final RpcCallback originalCallback) { + return (RpcCallback)originalCallback; + // The above cast works, but only due to technical details of the Java + // implementation. A more theoretically correct -- but less efficient -- + // implementation would be as follows: + // return new RpcCallback() { + // public void run(Type parameter) { + // originalCallback.run(parameter); + // } + // }; + } + + /** + * Take an {@code RpcCallback} accepting a specific message type and convert + * it to an {@code RpcCallback}. The generalized callback will + * accept any message object which has the same descriptor, and will convert + * it to the correct class before calling the original callback. However, + * if the generalized callback is given a message with a different descriptor, + * an exception will be thrown. + */ + public static + RpcCallback generalizeCallback( + final RpcCallback originalCallback, + final Class originalClass, + final Type defaultInstance) { + return new RpcCallback() { + @Override + public void run(final Message parameter) { + Type typedParameter; + try { + typedParameter = originalClass.cast(parameter); + } catch (ClassCastException ignored) { + typedParameter = copyAsType(defaultInstance, parameter); + } + originalCallback.run(typedParameter); + } + }; + } + + /** + * Creates a new message of type "Type" which is a copy of "source". "source" + * must have the same descriptor but may be a different class (e.g. + * DynamicMessage). + */ + @SuppressWarnings("unchecked") + private static Type copyAsType( + final Type typeDefaultInstance, final Message source) { + return (Type)typeDefaultInstance.newBuilderForType() + .mergeFrom(source) + .build(); + } + + /** + * Creates a callback which can only be called once. This may be useful for + * security, when passing a callback to untrusted code: most callbacks do + * not expect to be called more than once, so doing so may expose bugs if it + * is not prevented. + */ + public static + RpcCallback newOneTimeCallback( + final RpcCallback originalCallback) { + return new RpcCallback() { + private boolean alreadyCalled = false; + + @Override + public void run(final ParameterType parameter) { + synchronized(this) { + if (alreadyCalled) { + throw new AlreadyCalledException(); + } + alreadyCalled = true; + } + + originalCallback.run(parameter); + } + }; + } + + /** + * Exception thrown when a one-time callback is called more than once. + */ + public static final class AlreadyCalledException extends RuntimeException { + private static final long serialVersionUID = 5469741279507848266L; + + public AlreadyCalledException() { + super("This RpcCallback was already called and cannot be called " + + "multiple times."); + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/Service.java b/OsmAnd-java/src/com/google/protobuf/Service.java new file mode 100644 index 0000000000..541585f41f --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/Service.java @@ -0,0 +1,117 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * Abstract base interface for protocol-buffer-based RPC services. Services + * themselves are abstract classes (implemented either by servers or as + * stubs), but they subclass this base interface. The methods of this + * interface can be used to call the methods of the service without knowing + * its exact type at compile time (analogous to the Message interface). + * + *

Starting with version 2.3.0, RPC implementations should not try to build + * on this, but should instead provide code generator plugins which generate + * code specific to the particular RPC implementation. This way the generated + * code can be more appropriate for the implementation in use and can avoid + * unnecessary layers of indirection. + * + * @author kenton@google.com Kenton Varda + */ +public interface Service { + /** + * Get the {@code ServiceDescriptor} describing this service and its methods. + */ + Descriptors.ServiceDescriptor getDescriptorForType(); + + /** + *

Call a method of the service specified by MethodDescriptor. This is + * normally implemented as a simple {@code switch()} that calls the standard + * definitions of the service's methods. + * + *

Preconditions: + *

    + *
  • {@code method.getService() == getDescriptorForType()} + *
  • {@code request} is of the exact same class as the object returned by + * {@code getRequestPrototype(method)}. + *
  • {@code controller} is of the correct type for the RPC implementation + * being used by this Service. For stubs, the "correct type" depends + * on the RpcChannel which the stub is using. Server-side Service + * implementations are expected to accept whatever type of + * {@code RpcController} the server-side RPC implementation uses. + *
+ * + *

Postconditions: + *

    + *
  • {@code done} will be called when the method is complete. This may be + * before {@code callMethod()} returns or it may be at some point in + * the future. + *
  • The parameter to {@code done} is the response. It must be of the + * exact same type as would be returned by + * {@code getResponsePrototype(method)}. + *
  • If the RPC failed, the parameter to {@code done} will be + * {@code null}. Further details about the failure can be found by + * querying {@code controller}. + *
+ */ + void callMethod(Descriptors.MethodDescriptor method, + RpcController controller, + Message request, + RpcCallback done); + + /** + *

{@code callMethod()} requires that the request passed in is of a + * particular subclass of {@code Message}. {@code getRequestPrototype()} + * gets the default instances of this type for a given method. You can then + * call {@code Message.newBuilderForType()} on this instance to + * construct a builder to build an object which you can then pass to + * {@code callMethod()}. + * + *

Example: + *

+   *   MethodDescriptor method =
+   *     service.getDescriptorForType().findMethodByName("Foo");
+   *   Message request =
+   *     stub.getRequestPrototype(method).newBuilderForType()
+   *         .mergeFrom(input).build();
+   *   service.callMethod(method, request, callback);
+   * 
+ */ + Message getRequestPrototype(Descriptors.MethodDescriptor method); + + /** + * Like {@code getRequestPrototype()}, but gets a prototype of the response + * message. {@code getResponsePrototype()} is generally not needed because + * the {@code Service} implementation constructs the response message itself, + * but it may be useful in some cases to know ahead of time what type of + * object will be returned. + */ + Message getResponsePrototype(Descriptors.MethodDescriptor method); +} diff --git a/OsmAnd-java/src/com/google/protobuf/ServiceException.java b/OsmAnd-java/src/com/google/protobuf/ServiceException.java new file mode 100644 index 0000000000..c043a77582 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/ServiceException.java @@ -0,0 +1,44 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * Thrown by blocking RPC methods when a failure occurs. + * + * @author cpovirk@google.com (Chris Povirk) + */ +public final class ServiceException extends Exception { + private static final long serialVersionUID = -1219262335729891920L; + + public ServiceException(final String message) { + super(message); + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/TextFormat.java b/OsmAnd-java/src/com/google/protobuf/TextFormat.java new file mode 100644 index 0000000000..6639165d65 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/TextFormat.java @@ -0,0 +1,1352 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.CharBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.EnumDescriptor; +import com.google.protobuf.Descriptors.EnumValueDescriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; + +/** + * Provide ascii text parsing and formatting support for proto2 instances. + * The implementation largely follows google/protobuf/text_format.cc. + * + * @author wenboz@google.com Wenbo Zhu + * @author kenton@google.com Kenton Varda + */ +public final class TextFormat { + private TextFormat() { + } + + /** + * Outputs a textual representation of the Protocol Message supplied into + * the parameter output. (This representation is the new version of the + * classic "ProtocolPrinter" output from the original Protocol Buffer system) + */ + public static void print(final Message message, final Appendable output) + throws IOException { + final TextGenerator generator = new TextGenerator(output); + print(message, generator); + } + + /** Outputs a textual representation of {@code fields} to {@code output}. */ + public static void print(final UnknownFieldSet fields, + final Appendable output) + throws IOException { + final TextGenerator generator = new TextGenerator(output); + printUnknownFields(fields, generator); + } + + /** + * Like {@code print()}, but writes directly to a {@code String} and + * returns it. + */ + public static String printToString(final Message message) { + try { + final StringBuilder text = new StringBuilder(); + print(message, text); + return text.toString(); + } catch (IOException e) { + throw new RuntimeException( + "Writing to a StringBuilder threw an IOException (should never " + + "happen).", e); + } + } + + /** + * Like {@code print()}, but writes directly to a {@code String} and + * returns it. + */ + public static String printToString(final UnknownFieldSet fields) { + try { + final StringBuilder text = new StringBuilder(); + print(fields, text); + return text.toString(); + } catch (IOException e) { + throw new RuntimeException( + "Writing to a StringBuilder threw an IOException (should never " + + "happen).", e); + } + } + + private static void print(final Message message, + final TextGenerator generator) + throws IOException { + for (final Map.Entry field : + message.getAllFields().entrySet()) { + printField(field.getKey(), field.getValue(), generator); + } + printUnknownFields(message.getUnknownFields(), generator); + } + + public static void printField(final FieldDescriptor field, + final Object value, + final Appendable output) + throws IOException { + final TextGenerator generator = new TextGenerator(output); + printField(field, value, generator); + } + + public static String printFieldToString(final FieldDescriptor field, + final Object value) { + try { + final StringBuilder text = new StringBuilder(); + printField(field, value, text); + return text.toString(); + } catch (IOException e) { + throw new RuntimeException( + "Writing to a StringBuilder threw an IOException (should never " + + "happen).", e); + } + } + + @SuppressWarnings("unchecked") +private static void printField(final FieldDescriptor field, + final Object value, + final TextGenerator generator) + throws IOException { + if (field.isRepeated()) { + // Repeated field. Print each element. + for (final Object element : (List) value) { + printSingleField(field, element, generator); + } + } else { + printSingleField(field, value, generator); + } + } + + private static void printSingleField(final FieldDescriptor field, + final Object value, + final TextGenerator generator) + throws IOException { + if (field.isExtension()) { + generator.print("["); + // We special-case MessageSet elements for compatibility with proto1. + if (field.getContainingType().getOptions().getMessageSetWireFormat() + && (field.getType() == FieldDescriptor.Type.MESSAGE) + && (field.isOptional()) + // object equality + && (field.getExtensionScope() == field.getMessageType())) { + generator.print(field.getMessageType().getFullName()); + } else { + generator.print(field.getFullName()); + } + generator.print("]"); + } else { + if (field.getType() == FieldDescriptor.Type.GROUP) { + // Groups must be serialized with their original capitalization. + generator.print(field.getMessageType().getName()); + } else { + generator.print(field.getName()); + } + } + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + generator.print(" {\n"); + generator.indent(); + } else { + generator.print(": "); + } + + printFieldValue(field, value, generator); + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + generator.outdent(); + generator.print("}"); + } + generator.print("\n"); + } + + private static void printFieldValue(final FieldDescriptor field, + final Object value, + final TextGenerator generator) + throws IOException { + switch (field.getType()) { + case INT32: + case INT64: + case SINT32: + case SINT64: + case SFIXED32: + case SFIXED64: + case FLOAT: + case DOUBLE: + case BOOL: + // Good old toString() does what we want for these types. + generator.print(value.toString()); + break; + + case UINT32: + case FIXED32: + generator.print(unsignedToString((Integer) value)); + break; + + case UINT64: + case FIXED64: + generator.print(unsignedToString((Long) value)); + break; + + case STRING: + generator.print("\""); + generator.print(escapeText((String) value)); + generator.print("\""); + break; + + case BYTES: + generator.print("\""); + generator.print(escapeBytes((ByteString) value)); + generator.print("\""); + break; + + case ENUM: + generator.print(((EnumValueDescriptor) value).getName()); + break; + + case MESSAGE: + case GROUP: + print((Message) value, generator); + break; + } + } + + private static void printUnknownFields(final UnknownFieldSet unknownFields, + final TextGenerator generator) + throws IOException { + for (final Map.Entry entry : + unknownFields.asMap().entrySet()) { + @SuppressWarnings("unused") + final String prefix = entry.getKey().toString() + ": "; + final UnknownFieldSet.Field field = entry.getValue(); + + for (final long value : field.getVarintList()) { + generator.print(entry.getKey().toString()); + generator.print(": "); + generator.print(unsignedToString(value)); + generator.print("\n"); + } + for (final int value : field.getFixed32List()) { + generator.print(entry.getKey().toString()); + generator.print(": "); + // AVIAN missing dependency + generator.print(String.format((Locale) null, "0x%08x", value)); + generator.print("\n"); + } + for (final long value : field.getFixed64List()) { + generator.print(entry.getKey().toString()); + generator.print(": "); + // AVIAN missing dependency + generator.print(String.format((Locale) null, "0x%016x", value)); + generator.print("\n"); + } + for (final ByteString value : field.getLengthDelimitedList()) { + generator.print(entry.getKey().toString()); + generator.print(": \""); + generator.print(escapeBytes(value)); + generator.print("\"\n"); + } + for (final UnknownFieldSet value : field.getGroupList()) { + generator.print(entry.getKey().toString()); + generator.print(" {\n"); + generator.indent(); + printUnknownFields(value, generator); + generator.outdent(); + generator.print("}\n"); + } + } + } + + /** Convert an unsigned 32-bit integer to a string. */ + private static String unsignedToString(final int value) { + if (value >= 0) { + return Integer.toString(value); + } else { + return Long.toString(((long) value) & 0x00000000FFFFFFFFL); + } + } + + /** Convert an unsigned 64-bit integer to a string. */ + private static String unsignedToString(final long value) { + if (value >= 0) { + return Long.toString(value); + } else { + // Pull off the most-significant bit so that BigInteger doesn't think + // the number is negative, then set it again using setBit(). + return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL) + .setBit(63).toString(); + } + } + + /** + * An inner class for writing text to the output stream. + */ + private static final class TextGenerator { + private Appendable output; + private boolean atStartOfLine = true; + private final StringBuilder indent = new StringBuilder(); + + private TextGenerator(final Appendable output) { + this.output = output; + } + + /** + * Indent text by two spaces. After calling Indent(), two spaces will be + * inserted at the beginning of each line of text. Indent() may be called + * multiple times to produce deeper indents. + */ + public void indent() { + indent.append(" "); + } + + /** + * Reduces the current indent level by two spaces, or crashes if the indent + * level is zero. + */ + public void outdent() { + final int length = indent.length(); + if (length == 0) { + throw new IllegalArgumentException( + " Outdent() without matching Indent()."); + } + indent.delete(length - 2, length); + } + + /** + * Print text to the output stream. + */ + public void print(final CharSequence text) throws IOException { + final int size = text.length(); + int pos = 0; + + for (int i = 0; i < size; i++) { + if (text.charAt(i) == '\n') { + write(text.subSequence(pos, size), i - pos + 1); + pos = i + 1; + atStartOfLine = true; + } + } + write(text.subSequence(pos, size), size - pos); + } + + private void write(final CharSequence data, final int size) + throws IOException { + if (size == 0) { + return; + } + if (atStartOfLine) { + atStartOfLine = false; + output.append(indent); + } + output.append(data); + } + } + + // ================================================================= + // Parsing + + /** + * Represents a stream of tokens parsed from a {@code String}. + * + *

The Java standard library provides many classes that you might think + * would be useful for implementing this, but aren't. For example: + * + *

    + *
  • {@code java.io.StreamTokenizer}: This almost does what we want -- or, + * at least, something that would get us close to what we want -- except + * for one fatal flaw: It automatically un-escapes strings using Java + * escape sequences, which do not include all the escape sequences we + * need to support (e.g. '\x'). + *
  • {@code java.util.Scanner}: This seems like a great way at least to + * parse regular expressions out of a stream (so we wouldn't have to load + * the entire input into a single string before parsing). Sadly, + * {@code Scanner} requires that tokens be delimited with some delimiter. + * Thus, although the text "foo:" should parse to two tokens ("foo" and + * ":"), {@code Scanner} would recognize it only as a single token. + * Furthermore, {@code Scanner} provides no way to inspect the contents + * of delimiters, making it impossible to keep track of line and column + * numbers. + *
+ * + *

Luckily, Java's regular expression support does manage to be useful to + * us. (Barely: We need {@code Matcher.usePattern()}, which is new in + * Java 1.5.) So, we can use that, at least. Unfortunately, this implies + * that we need to have the entire input in one contiguous string. + */ + private static final class Tokenizer { + private final CharSequence text; + private final Matcher matcher; + private String currentToken; + + // The character index within this.text at which the current token begins. + private int pos = 0; + + // The line and column numbers of the current token. + private int line = 0; + private int column = 0; + + // The line and column numbers of the previous token (allows throwing + // errors *after* consuming). + private int previousLine = 0; + private int previousColumn = 0; + + // We use possesive quantifiers (*+ and ++) because otherwise the Java + // regex matcher has stack overflows on large inputs. + private static final Pattern WHITESPACE = + Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE); + private static final Pattern TOKEN = Pattern.compile( + "[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier + "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number + "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string + "\'([^\'\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string + Pattern.MULTILINE); + + private static final Pattern DOUBLE_INFINITY = Pattern.compile( + "-?inf(inity)?", + Pattern.CASE_INSENSITIVE); + private static final Pattern FLOAT_INFINITY = Pattern.compile( + "-?inf(inity)?f?", + Pattern.CASE_INSENSITIVE); + private static final Pattern FLOAT_NAN = Pattern.compile( + "nanf?", + Pattern.CASE_INSENSITIVE); + + /** Construct a tokenizer that parses tokens from the given text. */ + private Tokenizer(final CharSequence text) { + this.text = text; + this.matcher = WHITESPACE.matcher(text); + skipWhitespace(); + nextToken(); + } + + /** Are we at the end of the input? */ + public boolean atEnd() { + return currentToken.length() == 0; + } + + /** Advance to the next token. */ + public void nextToken() { + // AVIAN missing dependency +// if(true){ +// throw new UnsupportedOperationException(); +// } + previousLine = line; + previousColumn = column; + + // Advance the line counter to the current position. + while (pos < matcher.regionStart()) { + if (text.charAt(pos) == '\n') { + ++line; + column = 0; + } else { + ++column; + } + ++pos; + } + + // Match the next token. + if (matcher.regionStart() == matcher.regionEnd()) { + // EOF + currentToken = ""; + } else { + matcher.usePattern(TOKEN); + if (matcher.lookingAt()) { + currentToken = matcher.group(); + matcher.region(matcher.end(), matcher.regionEnd()); + } else { + // Take one character. + currentToken = String.valueOf(text.charAt(pos)); + matcher.region(pos + 1, matcher.regionEnd()); + } + + skipWhitespace(); + } + } + + /** + * Skip over any whitespace so that the matcher region starts at the next + * token. + */ + private void skipWhitespace() { + // AVIAN missing dependency +// if(true){ +// throw new UnsupportedOperationException(); +// } + matcher.usePattern(WHITESPACE); + if (matcher.lookingAt()) { + matcher.region(matcher.end(), matcher.regionEnd()); + } + } + + /** + * If the next token exactly matches {@code token}, consume it and return + * {@code true}. Otherwise, return {@code false} without doing anything. + */ + public boolean tryConsume(final String token) { + if (currentToken.equals(token)) { + nextToken(); + return true; + } else { + return false; + } + } + + /** + * If the next token exactly matches {@code token}, consume it. Otherwise, + * throw a {@link ParseException}. + */ + public void consume(final String token) throws ParseException { + if (!tryConsume(token)) { + throw parseException("Expected \"" + token + "\"."); + } + } + + /** + * Returns {@code true} if the next token is an integer, but does + * not consume it. + */ + public boolean lookingAtInteger() { + if (currentToken.length() == 0) { + return false; + } + + final char c = currentToken.charAt(0); + return ('0' <= c && c <= '9') || + c == '-' || c == '+'; + } + + /** + * If the next token is an identifier, consume it and return its value. + * Otherwise, throw a {@link ParseException}. + */ + public String consumeIdentifier() throws ParseException { + for (int i = 0; i < currentToken.length(); i++) { + final char c = currentToken.charAt(i); + if (('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9') || + (c == '_') || (c == '.')) { + // OK + } else { + throw parseException("Expected identifier."); + } + } + + final String result = currentToken; + nextToken(); + return result; + } + + /** + * If the next token is a 32-bit signed integer, consume it and return its + * value. Otherwise, throw a {@link ParseException}. + */ + public int consumeInt32() throws ParseException { + try { + final int result = parseInt32(currentToken); + nextToken(); + return result; + } catch (NumberFormatException e) { + throw integerParseException(e); + } + } + + /** + * If the next token is a 32-bit unsigned integer, consume it and return its + * value. Otherwise, throw a {@link ParseException}. + */ + public int consumeUInt32() throws ParseException { + try { + final int result = parseUInt32(currentToken); + nextToken(); + return result; + } catch (NumberFormatException e) { + throw integerParseException(e); + } + } + + /** + * If the next token is a 64-bit signed integer, consume it and return its + * value. Otherwise, throw a {@link ParseException}. + */ + public long consumeInt64() throws ParseException { + try { + final long result = parseInt64(currentToken); + nextToken(); + return result; + } catch (NumberFormatException e) { + throw integerParseException(e); + } + } + + /** + * If the next token is a 64-bit unsigned integer, consume it and return its + * value. Otherwise, throw a {@link ParseException}. + */ + public long consumeUInt64() throws ParseException { + try { + final long result = parseUInt64(currentToken); + nextToken(); + return result; + } catch (NumberFormatException e) { + throw integerParseException(e); + } + } + + /** + * If the next token is a double, consume it and return its value. + * Otherwise, throw a {@link ParseException}. + */ + public double consumeDouble() throws ParseException { + // We need to parse infinity and nan separately because + // Double.parseDouble() does not accept "inf", "infinity", or "nan". + if (DOUBLE_INFINITY.matcher(currentToken).matches()) { + final boolean negative = currentToken.startsWith("-"); + nextToken(); + return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; + } + if (currentToken.equalsIgnoreCase("nan")) { + nextToken(); + return Double.NaN; + } + try { + final double result = Double.parseDouble(currentToken); + nextToken(); + return result; + } catch (NumberFormatException e) { + throw floatParseException(e); + } + } + + /** + * If the next token is a float, consume it and return its value. + * Otherwise, throw a {@link ParseException}. + */ + public float consumeFloat() throws ParseException { + // We need to parse infinity and nan separately because + // Float.parseFloat() does not accept "inf", "infinity", or "nan". + if (FLOAT_INFINITY.matcher(currentToken).matches()) { + final boolean negative = currentToken.startsWith("-"); + nextToken(); + return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; + } + if (FLOAT_NAN.matcher(currentToken).matches()) { + nextToken(); + return Float.NaN; + } + try { + final float result = Float.parseFloat(currentToken); + nextToken(); + return result; + } catch (NumberFormatException e) { + throw floatParseException(e); + } + } + + /** + * If the next token is a boolean, consume it and return its value. + * Otherwise, throw a {@link ParseException}. + */ + public boolean consumeBoolean() throws ParseException { + if (currentToken.equals("true")) { + nextToken(); + return true; + } else if (currentToken.equals("false")) { + nextToken(); + return false; + } else { + throw parseException("Expected \"true\" or \"false\"."); + } + } + + /** + * If the next token is a string, consume it and return its (unescaped) + * value. Otherwise, throw a {@link ParseException}. + */ + public String consumeString() throws ParseException { + return consumeByteString().toStringUtf8(); + } + + /** + * If the next token is a string, consume it, unescape it as a + * {@link ByteString}, and return it. Otherwise, throw a + * {@link ParseException}. + */ + public ByteString consumeByteString() throws ParseException { + List list = new ArrayList(); + consumeByteString(list); + while (currentToken.startsWith("'") || currentToken.startsWith("\"")) { + consumeByteString(list); + } + return ByteString.copyFrom(list); + } + + /** + * Like {@link #consumeByteString()} but adds each token of the string to + * the given list. String literals (whether bytes or text) may come in + * multiple adjacent tokens which are automatically concatenated, like in + * C or Python. + */ + private void consumeByteString(List list) throws ParseException { + final char quote = currentToken.length() > 0 ? currentToken.charAt(0) + : '\0'; + if (quote != '\"' && quote != '\'') { + throw parseException("Expected string."); + } + + if (currentToken.length() < 2 || + currentToken.charAt(currentToken.length() - 1) != quote) { + throw parseException("String missing ending quote."); + } + + try { + final String escaped = + currentToken.substring(1, currentToken.length() - 1); + final ByteString result = unescapeBytes(escaped); + nextToken(); + list.add(result); + } catch (InvalidEscapeSequenceException e) { + throw parseException(e.getMessage()); + } + } + + /** + * Returns a {@link ParseException} with the current line and column + * numbers in the description, suitable for throwing. + */ + public ParseException parseException(final String description) { + // Note: People generally prefer one-based line and column numbers. + return new ParseException( + (line + 1) + ":" + (column + 1) + ": " + description); + } + + /** + * Returns a {@link ParseException} with the line and column numbers of + * the previous token in the description, suitable for throwing. + */ + public ParseException parseExceptionPreviousToken( + final String description) { + // Note: People generally prefer one-based line and column numbers. + return new ParseException( + (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description); + } + + /** + * Constructs an appropriate {@link ParseException} for the given + * {@code NumberFormatException} when trying to parse an integer. + */ + private ParseException integerParseException( + final NumberFormatException e) { + return parseException("Couldn't parse integer: " + e.getMessage()); + } + + /** + * Constructs an appropriate {@link ParseException} for the given + * {@code NumberFormatException} when trying to parse a float or double. + */ + private ParseException floatParseException(final NumberFormatException e) { + return parseException("Couldn't parse number: " + e.getMessage()); + } + } + + /** Thrown when parsing an invalid text format message. */ + public static class ParseException extends IOException { + private static final long serialVersionUID = 3196188060225107702L; + + public ParseException(final String message) { + super(message); + } + } + + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. + */ + public static void merge(final Readable input, + final Message.Builder builder) + throws IOException { + merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + } + + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. + */ + public static void merge(final CharSequence input, + final Message.Builder builder) + throws ParseException { + merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + } + + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. Extensions will be recognized if they are + * registered in {@code extensionRegistry}. + */ + public static void merge(final Readable input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws IOException { + // Read the entire input to a String then parse that. + + // If StreamTokenizer were not quite so crippled, or if there were a kind + // of Reader that could read in chunks that match some particular regex, + // or if we wanted to write a custom Reader to tokenize our stream, then + // we would not have to read to one big String. Alas, none of these is + // the case. Oh well. + + merge(toStringBuilder(input), extensionRegistry, builder); + } + + private static final int BUFFER_SIZE = 4096; + + // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer) + // overhead is worthwhile + private static StringBuilder toStringBuilder(final Readable input) + throws IOException { + final StringBuilder text = new StringBuilder(); + final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); + while (true) { + final int n = input.read(buffer); + if (n == -1) { + break; + } + buffer.flip(); + text.append(buffer, 0, n); + } + return text; + } + + /** + * Parse a text-format message from {@code input} and merge the contents + * into {@code builder}. Extensions will be recognized if they are + * registered in {@code extensionRegistry}. + */ + public static void merge(final CharSequence input, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws ParseException { + final Tokenizer tokenizer = new Tokenizer(input); + + while (!tokenizer.atEnd()) { + mergeField(tokenizer, extensionRegistry, builder); + } + } + + /** + * Parse a single field from {@code tokenizer} and merge it into + * {@code builder}. + */ + private static void mergeField(final Tokenizer tokenizer, + final ExtensionRegistry extensionRegistry, + final Message.Builder builder) + throws ParseException { + FieldDescriptor field; + final Descriptor type = builder.getDescriptorForType(); + ExtensionRegistry.ExtensionInfo extension = null; + + if (tokenizer.tryConsume("[")) { + // An extension. + final StringBuilder name = + new StringBuilder(tokenizer.consumeIdentifier()); + while (tokenizer.tryConsume(".")) { + name.append('.'); + name.append(tokenizer.consumeIdentifier()); + } + + extension = extensionRegistry.findExtensionByName(name.toString()); + + if (extension == null) { + throw tokenizer.parseExceptionPreviousToken( + "Extension \"" + name + "\" not found in the ExtensionRegistry."); + } else if (extension.descriptor.getContainingType() != type) { + throw tokenizer.parseExceptionPreviousToken( + "Extension \"" + name + "\" does not extend message type \"" + + type.getFullName() + "\"."); + } + + tokenizer.consume("]"); + + field = extension.descriptor; + } else { + final String name = tokenizer.consumeIdentifier(); + field = type.findFieldByName(name); + + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their field + // names. + if (field == null) { + // Explicitly specify US locale so that this code does not break when + // executing in Turkey. + final String lowerName = name.toLowerCase(Locale.US); + field = type.findFieldByName(lowerName); + // If the case-insensitive match worked but the field is NOT a group, + if (field != null && field.getType() != FieldDescriptor.Type.GROUP) { + field = null; + } + } + // Again, special-case group names as described above. + if (field != null && field.getType() == FieldDescriptor.Type.GROUP && + !field.getMessageType().getName().equals(name)) { + field = null; + } + + if (field == null) { + throw tokenizer.parseExceptionPreviousToken( + "Message type \"" + type.getFullName() + + "\" has no field named \"" + name + "\"."); + } + } + + Object value = null; + + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + tokenizer.tryConsume(":"); // optional + + final String endToken; + if (tokenizer.tryConsume("<")) { + endToken = ">"; + } else { + tokenizer.consume("{"); + endToken = "}"; + } + + final Message.Builder subBuilder; + if (extension == null) { + subBuilder = builder.newBuilderForField(field); + } else { + subBuilder = extension.defaultInstance.newBuilderForType(); + } + + while (!tokenizer.tryConsume(endToken)) { + if (tokenizer.atEnd()) { + throw tokenizer.parseException( + "Expected \"" + endToken + "\"."); + } + mergeField(tokenizer, extensionRegistry, subBuilder); + } + + value = subBuilder.build(); + + } else { + tokenizer.consume(":"); + + switch (field.getType()) { + case INT32: + case SINT32: + case SFIXED32: + value = tokenizer.consumeInt32(); + break; + + case INT64: + case SINT64: + case SFIXED64: + value = tokenizer.consumeInt64(); + break; + + case UINT32: + case FIXED32: + value = tokenizer.consumeUInt32(); + break; + + case UINT64: + case FIXED64: + value = tokenizer.consumeUInt64(); + break; + + case FLOAT: + value = tokenizer.consumeFloat(); + break; + + case DOUBLE: + value = tokenizer.consumeDouble(); + break; + + case BOOL: + value = tokenizer.consumeBoolean(); + break; + + case STRING: + value = tokenizer.consumeString(); + break; + + case BYTES: + value = tokenizer.consumeByteString(); + break; + + case ENUM: + final EnumDescriptor enumType = field.getEnumType(); + + if (tokenizer.lookingAtInteger()) { + final int number = tokenizer.consumeInt32(); + value = enumType.findValueByNumber(number); + if (value == null) { + throw tokenizer.parseExceptionPreviousToken( + "Enum type \"" + enumType.getFullName() + + "\" has no value with number " + number + '.'); + } + } else { + final String id = tokenizer.consumeIdentifier(); + value = enumType.findValueByName(id); + if (value == null) { + throw tokenizer.parseExceptionPreviousToken( + "Enum type \"" + enumType.getFullName() + + "\" has no value named \"" + id + "\"."); + } + } + + break; + + case MESSAGE: + case GROUP: + throw new RuntimeException("Can't get here."); + } + } + + if (field.isRepeated()) { + builder.addRepeatedField(field, value); + } else { + builder.setField(field, value); + } + } + + // ================================================================= + // Utility functions + // + // Some of these methods are package-private because Descriptors.java uses + // them. + + /** + * Escapes bytes in the format used in protocol buffer text format, which + * is the same as the format used for C string literals. All bytes + * that are not printable 7-bit ASCII characters are escaped, as well as + * backslash, single-quote, and double-quote characters. Characters for + * which no defined short-hand escape sequence is defined will be escaped + * using 3-digit octal sequences. + */ + static String escapeBytes(final ByteString input) { + final StringBuilder builder = new StringBuilder(input.size()); + for (int i = 0; i < input.size(); i++) { + final byte b = input.byteAt(i); + switch (b) { + // Java does not recognize \a or \v, apparently. + case 0x07: builder.append("\\a" ); break; + case '\b': builder.append("\\b" ); break; + case '\f': builder.append("\\f" ); break; + case '\n': builder.append("\\n" ); break; + case '\r': builder.append("\\r" ); break; + case '\t': builder.append("\\t" ); break; + case 0x0b: builder.append("\\v" ); break; + case '\\': builder.append("\\\\"); break; + case '\'': builder.append("\\\'"); break; + case '"' : builder.append("\\\""); break; + default: + if (b >= 0x20) { + builder.append((char) b); + } else { + builder.append('\\'); + builder.append((char) ('0' + ((b >>> 6) & 3))); + builder.append((char) ('0' + ((b >>> 3) & 7))); + builder.append((char) ('0' + (b & 7))); + } + break; + } + } + return builder.toString(); + } + + /** + * Un-escape a byte sequence as escaped using + * {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with + * "\x") are also recognized. + */ + static ByteString unescapeBytes(final CharSequence input) + throws InvalidEscapeSequenceException { + final byte[] result = new byte[input.length()]; + int pos = 0; + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + if (c == '\\') { + if (i + 1 < input.length()) { + ++i; + c = input.charAt(i); + if (isOctal(c)) { + // Octal escape. + int code = digitValue(c); + if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) { + ++i; + code = code * 8 + digitValue(input.charAt(i)); + } + if (i + 1 < input.length() && isOctal(input.charAt(i + 1))) { + ++i; + code = code * 8 + digitValue(input.charAt(i)); + } + result[pos++] = (byte)code; + } else { + switch (c) { + case 'a' : result[pos++] = 0x07; break; + case 'b' : result[pos++] = '\b'; break; + case 'f' : result[pos++] = '\f'; break; + case 'n' : result[pos++] = '\n'; break; + case 'r' : result[pos++] = '\r'; break; + case 't' : result[pos++] = '\t'; break; + case 'v' : result[pos++] = 0x0b; break; + case '\\': result[pos++] = '\\'; break; + case '\'': result[pos++] = '\''; break; + case '"' : result[pos++] = '\"'; break; + + case 'x': + // hex escape + int code = 0; + if (i + 1 < input.length() && isHex(input.charAt(i + 1))) { + ++i; + code = digitValue(input.charAt(i)); + } else { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\x' with no digits"); + } + if (i + 1 < input.length() && isHex(input.charAt(i + 1))) { + ++i; + code = code * 16 + digitValue(input.charAt(i)); + } + result[pos++] = (byte)code; + break; + + default: + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\" + c + '\''); + } + } + } else { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\' at end of string."); + } + } else { + result[pos++] = (byte)c; + } + } + + return ByteString.copyFrom(result, 0, pos); + } + + /** + * Thrown by {@link TextFormat#unescapeBytes} and + * {@link TextFormat#unescapeText} when an invalid escape sequence is seen. + */ + static class InvalidEscapeSequenceException extends IOException { + private static final long serialVersionUID = -8164033650142593304L; + + InvalidEscapeSequenceException(final String description) { + super(description); + } + } + + /** + * Like {@link #escapeBytes(ByteString)}, but escapes a text string. + * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped + * individually as a 3-digit octal escape. Yes, it's weird. + */ + static String escapeText(final String input) { + return escapeBytes(ByteString.copyFromUtf8(input)); + } + + /** + * Un-escape a text string as escaped using {@link #escapeText(String)}. + * Two-digit hex escapes (starting with "\x") are also recognized. + */ + static String unescapeText(final String input) + throws InvalidEscapeSequenceException { + return unescapeBytes(input).toStringUtf8(); + } + + /** Is this an octal digit? */ + private static boolean isOctal(final char c) { + return '0' <= c && c <= '7'; + } + + /** Is this a hex digit? */ + private static boolean isHex(final char c) { + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'); + } + + /** + * Interpret a character as a digit (in any base up to 36) and return the + * numeric value. This is like {@code Character.digit()} but we don't accept + * non-ASCII digits. + */ + private static int digitValue(final char c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } else if ('a' <= c && c <= 'z') { + return c - 'a' + 10; + } else { + return c - 'A' + 10; + } + } + + /** + * Parse a 32-bit signed integer from the text. Unlike the Java standard + * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" + * and "0" to signify hexidecimal and octal numbers, respectively. + */ + static int parseInt32(final String text) throws NumberFormatException { + return (int) parseInteger(text, true, false); + } + + /** + * Parse a 32-bit unsigned integer from the text. Unlike the Java standard + * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" + * and "0" to signify hexidecimal and octal numbers, respectively. The + * result is coerced to a (signed) {@code int} when returned since Java has + * no unsigned integer type. + */ + static int parseUInt32(final String text) throws NumberFormatException { + return (int) parseInteger(text, false, false); + } + + /** + * Parse a 64-bit signed integer from the text. Unlike the Java standard + * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" + * and "0" to signify hexidecimal and octal numbers, respectively. + */ + static long parseInt64(final String text) throws NumberFormatException { + return parseInteger(text, true, true); + } + + /** + * Parse a 64-bit unsigned integer from the text. Unlike the Java standard + * {@code Integer.parseInt()}, this function recognizes the prefixes "0x" + * and "0" to signify hexidecimal and octal numbers, respectively. The + * result is coerced to a (signed) {@code long} when returned since Java has + * no unsigned long type. + */ + static long parseUInt64(final String text) throws NumberFormatException { + return parseInteger(text, false, true); + } + + private static long parseInteger(final String text, + final boolean isSigned, + final boolean isLong) + throws NumberFormatException { + int pos = 0; + + boolean negative = false; + if (text.startsWith("-", pos)) { + if (!isSigned) { + throw new NumberFormatException("Number must be positive: " + text); + } + ++pos; + negative = true; + } + + int radix = 10; + if (text.startsWith("0x", pos)) { + pos += 2; + radix = 16; + } else if (text.startsWith("0", pos)) { + radix = 8; + } + + final String numberText = text.substring(pos); + + long result = 0; + if (numberText.length() < 16) { + // Can safely assume no overflow. + result = Long.parseLong(numberText, radix); + if (negative) { + result = -result; + } + + // Check bounds. + // No need to check for 64-bit numbers since they'd have to be 16 chars + // or longer to overflow. + if (!isLong) { + if (isSigned) { + if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) { + throw new NumberFormatException( + "Number out of range for 32-bit signed integer: " + text); + } + } else { + if (result >= (1L << 32) || result < 0) { + throw new NumberFormatException( + "Number out of range for 32-bit unsigned integer: " + text); + } + } + } + } else { + BigInteger bigValue = new BigInteger(numberText, radix); + if (negative) { + bigValue = bigValue.negate(); + } + + // Check bounds. + if (!isLong) { + if (isSigned) { + if (bigValue.bitLength() > 31) { + throw new NumberFormatException( + "Number out of range for 32-bit signed integer: " + text); + } + } else { + if (bigValue.bitLength() > 32) { + throw new NumberFormatException( + "Number out of range for 32-bit unsigned integer: " + text); + } + } + } else { + if (isSigned) { + if (bigValue.bitLength() > 63) { + throw new NumberFormatException( + "Number out of range for 64-bit signed integer: " + text); + } + } else { + if (bigValue.bitLength() > 64) { + throw new NumberFormatException( + "Number out of range for 64-bit unsigned integer: " + text); + } + } + } + + result = bigValue.longValue(); + } + + return result; + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/UninitializedMessageException.java b/OsmAnd-java/src/com/google/protobuf/UninitializedMessageException.java new file mode 100644 index 0000000000..8743c1200a --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/UninitializedMessageException.java @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.util.Collections; +import java.util.List; + +/** + * Thrown when attempting to build a protocol message that is missing required + * fields. This is a {@code RuntimeException} because it normally represents + * a programming error: it happens when some code which constructs a message + * fails to set all the fields. {@code parseFrom()} methods do not + * throw this; they throw an {@link InvalidProtocolBufferException} if + * required fields are missing, because it is not a programming error to + * receive an incomplete message. In other words, + * {@code UninitializedMessageException} should never be thrown by correct + * code, but {@code InvalidProtocolBufferException} might be. + * + * @author kenton@google.com Kenton Varda + */ +public class UninitializedMessageException extends RuntimeException { + private static final long serialVersionUID = -7466929953374883507L; + + public UninitializedMessageException(final MessageLite message) { + super("Message was missing required fields. (Lite runtime could not " + + "determine which fields were missing)."); + missingFields = null; + } + + public UninitializedMessageException(final List missingFields) { + super(buildDescription(missingFields)); + this.missingFields = missingFields; + } + + private final List missingFields; + + /** + * Get a list of human-readable names of required fields missing from this + * message. Each name is a full path to a field, e.g. "foo.bar[5].baz". + * Returns null if the lite runtime was used, since it lacks the ability to + * find missing fields. + */ + public List getMissingFields() { + return Collections.unmodifiableList(missingFields); + } + + /** + * Converts this exception to an {@link InvalidProtocolBufferException}. + * When a parsed message is missing required fields, this should be thrown + * instead of {@code UninitializedMessageException}. + */ + public InvalidProtocolBufferException asInvalidProtocolBufferException() { + return new InvalidProtocolBufferException(getMessage()); + } + + /** Construct the description string for this exception. */ + private static String buildDescription(final List missingFields) { + final StringBuilder description = + new StringBuilder("Message missing required fields: "); + boolean first = true; + for (final String field : missingFields) { + if (first) { + first = false; + } else { + description.append(", "); + } + description.append(field); + } + return description.toString(); + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/UnknownFieldSet.java b/OsmAnd-java/src/com/google/protobuf/UnknownFieldSet.java new file mode 100644 index 0000000000..37364433be --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/UnknownFieldSet.java @@ -0,0 +1,980 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream; + +/** + * {@code UnknownFieldSet} is used to keep track of fields which were seen when + * parsing a protocol message but whose field numbers or types are unrecognized. + * This most frequently occurs when new fields are added to a message type + * and then messages containing those feilds are read by old software that was + * compiled before the new types were added. + * + *

Every {@link Message} contains an {@code UnknownFieldSet} (and every + * {@link Message.Builder} contains an {@link Builder}). + * + *

Most users will never need to use this class. + * + * @author kenton@google.com Kenton Varda + */ +public final class UnknownFieldSet implements MessageLite { + private UnknownFieldSet() {} + + /** Create a new {@link Builder}. */ + public static Builder newBuilder() { + return Builder.create(); + } + + /** + * Create a new {@link Builder} and initialize it to be a copy + * of {@code copyFrom}. + */ + public static Builder newBuilder(final UnknownFieldSet copyFrom) { + return newBuilder().mergeFrom(copyFrom); + } + + /** Get an empty {@code UnknownFieldSet}. */ + public static UnknownFieldSet getDefaultInstance() { + return defaultInstance; + } + @Override +public UnknownFieldSet getDefaultInstanceForType() { + return defaultInstance; + } + private static final UnknownFieldSet defaultInstance = + new UnknownFieldSet(Collections.emptyMap()); + + /** + * Construct an {@code UnknownFieldSet} around the given map. The map is + * expected to be immutable. + */ + private UnknownFieldSet(final Map fields) { + this.fields = fields; + } + private Map fields; + + @Override + public boolean equals(final Object other) { + if (this == other) { + return true; + } + return (other instanceof UnknownFieldSet) && + fields.equals(((UnknownFieldSet) other).fields); + } + + @Override + public int hashCode() { + return fields.hashCode(); + } + + /** Get a map of fields in the set by number. */ + public Map asMap() { + return fields; + } + + /** Check if the given field number is present in the set. */ + public boolean hasField(final int number) { + return fields.containsKey(number); + } + + /** + * Get a field by number. Returns an empty field if not present. Never + * returns {@code null}. + */ + public Field getField(final int number) { + final Field result = fields.get(number); + return (result == null) ? Field.getDefaultInstance() : result; + } + + /** Serializes the set and writes it to {@code output}. */ + @Override +public void writeTo(final CodedOutputStream output) throws IOException { + for (final Map.Entry entry : fields.entrySet()) { + entry.getValue().writeTo(entry.getKey(), output); + } + } + + /** + * Converts the set to a string in protocol buffer text format. This is + * just a trivial wrapper around + * {@link TextFormat#printToString(UnknownFieldSet)}. + */ + @Override + public String toString() { + return TextFormat.printToString(this); + } + + /** + * Serializes the message to a {@code ByteString} and returns it. This is + * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. + */ + @Override +public ByteString toByteString() { + try { + final ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize()); + writeTo(out.getCodedOutput()); + return out.build(); + } catch (final IOException e) { + throw new RuntimeException( + "Serializing to a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + /** + * Serializes the message to a {@code byte} array and returns it. This is + * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. + */ + @Override +public byte[] toByteArray() { + try { + final byte[] result = new byte[getSerializedSize()]; + final CodedOutputStream output = CodedOutputStream.newInstance(result); + writeTo(output); + output.checkNoSpaceLeft(); + return result; + } catch (final IOException e) { + throw new RuntimeException( + "Serializing to a byte array threw an IOException " + + "(should never happen).", e); + } + } + + /** + * Serializes the message and writes it to {@code output}. This is just a + * trivial wrapper around {@link #writeTo(CodedOutputStream)}. + */ + @Override +public void writeTo(final OutputStream output) throws IOException { + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + writeTo(codedOutput); + codedOutput.flush(); + } + + @Override +public void writeDelimitedTo(OutputStream output) throws IOException { + final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + codedOutput.writeRawVarint32(getSerializedSize()); + writeTo(codedOutput); + codedOutput.flush(); + } + + /** Get the number of bytes required to encode this set. */ + @Override +public int getSerializedSize() { + int result = 0; + for (final Map.Entry entry : fields.entrySet()) { + result += entry.getValue().getSerializedSize(entry.getKey()); + } + return result; + } + + /** + * Serializes the set and writes it to {@code output} using + * {@code MessageSet} wire format. + */ + public void writeAsMessageSetTo(final CodedOutputStream output) + throws IOException { + for (final Map.Entry entry : fields.entrySet()) { + entry.getValue().writeAsMessageSetExtensionTo( + entry.getKey(), output); + } + } + + /** + * Get the number of bytes required to encode this set using + * {@code MessageSet} wire format. + */ + public int getSerializedSizeAsMessageSet() { + int result = 0; + for (final Map.Entry entry : fields.entrySet()) { + result += entry.getValue().getSerializedSizeAsMessageSetExtension( + entry.getKey()); + } + return result; + } + + @Override +public boolean isInitialized() { + // UnknownFieldSets do not have required fields, so they are always + // initialized. + return true; + } + + /** Parse an {@code UnknownFieldSet} from the given input stream. */ + public static UnknownFieldSet parseFrom(final CodedInputStream input) + throws IOException { + return newBuilder().mergeFrom(input).build(); + } + + /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ + public static UnknownFieldSet parseFrom(final ByteString data) + throws InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).build(); + } + + /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ + public static UnknownFieldSet parseFrom(final byte[] data) + throws InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).build(); + } + + /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */ + public static UnknownFieldSet parseFrom(final InputStream input) + throws IOException { + return newBuilder().mergeFrom(input).build(); + } + + @Override +public Builder newBuilderForType() { + return newBuilder(); + } + + @Override +public Builder toBuilder() { + return newBuilder().mergeFrom(this); + } + + /** + * Builder for {@link UnknownFieldSet}s. + * + *

Note that this class maintains {@link Field.Builder}s for all fields + * in the set. Thus, adding one element to an existing {@link Field} does not + * require making a copy. This is important for efficient parsing of + * unknown repeated fields. However, it implies that {@link Field}s cannot + * be constructed independently, nor can two {@link UnknownFieldSet}s share + * the same {@code Field} object. + * + *

Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}. + */ + public static final class Builder implements MessageLite.Builder { + // This constructor should never be called directly (except from 'create'). + private Builder() {} + + private Map fields; + + // Optimization: We keep around a builder for the last field that was + // modified so that we can efficiently add to it multiple times in a + // row (important when parsing an unknown repeated field). + private int lastFieldNumber; + private Field.Builder lastField; + + private static Builder create() { + Builder builder = new Builder(); + builder.reinitialize(); + return builder; + } + + /** + * Get a field builder for the given field number which includes any + * values that already exist. + */ + private Field.Builder getFieldBuilder(final int number) { + if (lastField != null) { + if (number == lastFieldNumber) { + return lastField; + } + // Note: addField() will reset lastField and lastFieldNumber. + addField(lastFieldNumber, lastField.build()); + } + if (number == 0) { + return null; + } else { + final Field existing = fields.get(number); + lastFieldNumber = number; + lastField = Field.newBuilder(); + if (existing != null) { + lastField.mergeFrom(existing); + } + return lastField; + } + } + + /** + * Build the {@link UnknownFieldSet} and return it. + * + *

Once {@code build()} has been called, the {@code Builder} will no + * longer be usable. Calling any method after {@code build()} will result + * in undefined behavior and can cause a {@code NullPointerException} to be + * thrown. + */ + @Override + public UnknownFieldSet build() { + getFieldBuilder(0); // Force lastField to be built. + final UnknownFieldSet result; + if (fields.isEmpty()) { + result = getDefaultInstance(); + } else { + result = new UnknownFieldSet(Collections.unmodifiableMap(fields)); + } + fields = null; + return result; + } + + @Override + public UnknownFieldSet buildPartial() { + // No required fields, so this is the same as build(). + return build(); + } + + @Override + public Builder clone() { + getFieldBuilder(0); // Force lastField to be built. + return UnknownFieldSet.newBuilder().mergeFrom( + new UnknownFieldSet(fields)); + } + + @Override + public UnknownFieldSet getDefaultInstanceForType() { + return UnknownFieldSet.getDefaultInstance(); + } + + private void reinitialize() { + fields = Collections.emptyMap(); + lastFieldNumber = 0; + lastField = null; + } + + /** Reset the builder to an empty set. */ + @Override + public Builder clear() { + reinitialize(); + return this; + } + + /** + * Merge the fields from {@code other} into this set. If a field number + * exists in both sets, {@code other}'s values for that field will be + * appended to the values in this set. + */ + public Builder mergeFrom(final UnknownFieldSet other) { + if (other != getDefaultInstance()) { + for (final Map.Entry entry : other.fields.entrySet()) { + mergeField(entry.getKey(), entry.getValue()); + } + } + return this; + } + + /** + * Add a field to the {@code UnknownFieldSet}. If a field with the same + * number already exists, the two are merged. + */ + public Builder mergeField(final int number, final Field field) { + if (number == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + if (hasField(number)) { + getFieldBuilder(number).mergeFrom(field); + } else { + // Optimization: We could call getFieldBuilder(number).mergeFrom(field) + // in this case, but that would create a copy of the Field object. + // We'd rather reuse the one passed to us, so call addField() instead. + addField(number, field); + } + return this; + } + + /** + * Convenience method for merging a new field containing a single varint + * value. This is used in particular when an unknown enum value is + * encountered. + */ + public Builder mergeVarintField(final int number, final int value) { + if (number == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + getFieldBuilder(number).addVarint(value); + return this; + } + + /** Check if the given field number is present in the set. */ + public boolean hasField(final int number) { + if (number == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + return number == lastFieldNumber || fields.containsKey(number); + } + + /** + * Add a field to the {@code UnknownFieldSet}. If a field with the same + * number already exists, it is removed. + */ + public Builder addField(final int number, final Field field) { + if (number == 0) { + throw new IllegalArgumentException("Zero is not a valid field number."); + } + if (lastField != null && lastFieldNumber == number) { + // Discard this. + lastField = null; + lastFieldNumber = 0; + } + if (fields.isEmpty()) { + fields = new TreeMap(); + } + fields.put(number, field); + return this; + } + + /** + * Get all present {@code Field}s as an immutable {@code Map}. If more + * fields are added, the changes may or may not be reflected in this map. + */ + public Map asMap() { + getFieldBuilder(0); // Force lastField to be built. + return Collections.unmodifiableMap(fields); + } + + /** + * Parse an entire message from {@code input} and merge its fields into + * this set. + */ + @Override + public Builder mergeFrom(final CodedInputStream input) throws IOException { + while (true) { + final int tag = input.readTag(); + if (tag == 0 || !mergeFieldFrom(tag, input)) { + break; + } + } + return this; + } + + /** + * Parse a single field from {@code input} and merge it into this set. + * @param tag The field's tag number, which was already parsed. + * @return {@code false} if the tag is an engroup tag. + */ + public boolean mergeFieldFrom(final int tag, final CodedInputStream input) + throws IOException { + final int number = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + getFieldBuilder(number).addVarint(input.readInt64()); + return true; + case WireFormat.WIRETYPE_FIXED64: + getFieldBuilder(number).addFixed64(input.readFixed64()); + return true; + case WireFormat.WIRETYPE_LENGTH_DELIMITED: + getFieldBuilder(number).addLengthDelimited(input.readBytes()); + return true; + case WireFormat.WIRETYPE_START_GROUP: + final Builder subBuilder = newBuilder(); + input.readGroup(number, subBuilder, + ExtensionRegistry.getEmptyRegistry()); + getFieldBuilder(number).addGroup(subBuilder.build()); + return true; + case WireFormat.WIRETYPE_END_GROUP: + return false; + case WireFormat.WIRETYPE_FIXED32: + getFieldBuilder(number).addFixed32(input.readFixed32()); + return true; + default: + throw InvalidProtocolBufferException.invalidWireType(); + } + } + + /** + * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the + * set being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + @Override + public Builder mergeFrom(final ByteString data) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = data.newCodedInput(); + mergeFrom(input); + input.checkLastTagWas(0); + return this; + } catch (final InvalidProtocolBufferException e) { + throw e; + } catch (final IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should " + + "never happen).", e); + } + } + + /** + * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the + * set being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + @Override + public Builder mergeFrom(final byte[] data) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = CodedInputStream.newInstance(data); + mergeFrom(input); + input.checkLastTagWas(0); + return this; + } catch (final InvalidProtocolBufferException e) { + throw e; + } catch (final IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + /** + * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the + * set being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + @Override + public Builder mergeFrom(final InputStream input) throws IOException { + final CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput); + codedInput.checkLastTagWas(0); + return this; + } + + @Override + public boolean mergeDelimitedFrom(InputStream input) + throws IOException { + final int firstByte = input.read(); + if (firstByte == -1) { + return false; + } + final int size = CodedInputStream.readRawVarint32(firstByte, input); + final InputStream limitedInput = new LimitedInputStream(input, size); + mergeFrom(limitedInput); + return true; + } + + @Override + public boolean mergeDelimitedFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) throws IOException { + // UnknownFieldSet has no extensions. + return mergeDelimitedFrom(input); + } + + @Override + public Builder mergeFrom( + CodedInputStream input, + ExtensionRegistryLite extensionRegistry) throws IOException { + // UnknownFieldSet has no extensions. + return mergeFrom(input); + } + + @Override + public Builder mergeFrom( + ByteString data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + // UnknownFieldSet has no extensions. + return mergeFrom(data); + } + + @Override + public Builder mergeFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { + try { + final CodedInputStream input = + CodedInputStream.newInstance(data, off, len); + mergeFrom(input); + input.checkLastTagWas(0); + return this; + } catch (InvalidProtocolBufferException e) { + throw e; + } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should " + + "never happen).", e); + } + } + + @Override + public Builder mergeFrom( + byte[] data, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + // UnknownFieldSet has no extensions. + return mergeFrom(data); + } + + @Override + public Builder mergeFrom( + byte[] data, int off, int len, + ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + // UnknownFieldSet has no extensions. + return mergeFrom(data, off, len); + } + + @Override + public Builder mergeFrom( + InputStream input, + ExtensionRegistryLite extensionRegistry) throws IOException { + // UnknownFieldSet has no extensions. + return mergeFrom(input); + } + + @Override + public boolean isInitialized() { + // UnknownFieldSets do not have required fields, so they are always + // initialized. + return true; + } + } + + /** + * Represents a single field in an {@code UnknownFieldSet}. + * + *

A {@code Field} consists of five lists of values. The lists correspond + * to the five "wire types" used in the protocol buffer binary format. + * The wire type of each field can be determined from the encoded form alone, + * without knowing the field's declared type. So, we are able to parse + * unknown values at least this far and separate them. Normally, only one + * of the five lists will contain any values, since it is impossible to + * define a valid message type that declares two different types for the + * same field number. However, the code is designed to allow for the case + * where the same unknown field number is encountered using multiple different + * wire types. + * + *

{@code Field} is an immutable class. To construct one, you must use a + * {@link Builder}. + * + * @see UnknownFieldSet + */ + public static final class Field { + private Field() {} + + /** Construct a new {@link Builder}. */ + public static Builder newBuilder() { + return Builder.create(); + } + + /** + * Construct a new {@link Builder} and initialize it to a copy of + * {@code copyFrom}. + */ + public static Builder newBuilder(final Field copyFrom) { + return newBuilder().mergeFrom(copyFrom); + } + + /** Get an empty {@code Field}. */ + public static Field getDefaultInstance() { + return fieldDefaultInstance; + } + private static final Field fieldDefaultInstance = newBuilder().build(); + + /** Get the list of varint values for this field. */ + public List getVarintList() { return varint; } + + /** Get the list of fixed32 values for this field. */ + public List getFixed32List() { return fixed32; } + + /** Get the list of fixed64 values for this field. */ + public List getFixed64List() { return fixed64; } + + /** Get the list of length-delimited values for this field. */ + public List getLengthDelimitedList() { return lengthDelimited; } + + /** + * Get the list of embedded group values for this field. These are + * represented using {@link UnknownFieldSet}s rather than {@link Message}s + * since the group's type is presumably unknown. + */ + public List getGroupList() { return group; } + + @Override + public boolean equals(final Object other) { + if (this == other) { + return true; + } + if (!(other instanceof Field)) { + return false; + } + return Arrays.equals(getIdentityArray(), + ((Field) other).getIdentityArray()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(getIdentityArray()); + } + + /** + * Returns the array of objects to be used to uniquely identify this + * {@link Field} instance. + */ + private Object[] getIdentityArray() { + return new Object[] { + varint, + fixed32, + fixed64, + lengthDelimited, + group}; + } + + /** + * Serializes the field, including field number, and writes it to + * {@code output}. + */ + public void writeTo(final int fieldNumber, final CodedOutputStream output) + throws IOException { + for (final long value : varint) { + output.writeUInt64(fieldNumber, value); + } + for (final int value : fixed32) { + output.writeFixed32(fieldNumber, value); + } + for (final long value : fixed64) { + output.writeFixed64(fieldNumber, value); + } + for (final ByteString value : lengthDelimited) { + output.writeBytes(fieldNumber, value); + } + for (final UnknownFieldSet value : group) { + output.writeGroup(fieldNumber, value); + } + } + + /** + * Get the number of bytes required to encode this field, including field + * number. + */ + public int getSerializedSize(final int fieldNumber) { + int result = 0; + for (final long value : varint) { + result += CodedOutputStream.computeUInt64Size(fieldNumber, value); + } + for (final int value : fixed32) { + result += CodedOutputStream.computeFixed32Size(fieldNumber, value); + } + for (final long value : fixed64) { + result += CodedOutputStream.computeFixed64Size(fieldNumber, value); + } + for (final ByteString value : lengthDelimited) { + result += CodedOutputStream.computeBytesSize(fieldNumber, value); + } + for (final UnknownFieldSet value : group) { + result += CodedOutputStream.computeGroupSize(fieldNumber, value); + } + return result; + } + + /** + * Serializes the field, including field number, and writes it to + * {@code output}, using {@code MessageSet} wire format. + */ + public void writeAsMessageSetExtensionTo( + final int fieldNumber, + final CodedOutputStream output) + throws IOException { + for (final ByteString value : lengthDelimited) { + output.writeRawMessageSetExtension(fieldNumber, value); + } + } + + /** + * Get the number of bytes required to encode this field, including field + * number, using {@code MessageSet} wire format. + */ + public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) { + int result = 0; + for (final ByteString value : lengthDelimited) { + result += CodedOutputStream.computeRawMessageSetExtensionSize( + fieldNumber, value); + } + return result; + } + + private List varint; + private List fixed32; + private List fixed64; + private List lengthDelimited; + private List group; + + /** + * Used to build a {@link Field} within an {@link UnknownFieldSet}. + * + *

Use {@link Field#newBuilder()} to construct a {@code Builder}. + */ + public static final class Builder { + // This constructor should never be called directly (except from 'create'). + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new Field(); + return builder; + } + + private Field result; + + /** + * Build the field. After {@code build()} has been called, the + * {@code Builder} is no longer usable. Calling any other method will + * result in undefined behavior and can cause a + * {@code NullPointerException} to be thrown. + */ + public Field build() { + if (result.varint == null) { + result.varint = Collections.emptyList(); + } else { + result.varint = Collections.unmodifiableList(result.varint); + } + if (result.fixed32 == null) { + result.fixed32 = Collections.emptyList(); + } else { + result.fixed32 = Collections.unmodifiableList(result.fixed32); + } + if (result.fixed64 == null) { + result.fixed64 = Collections.emptyList(); + } else { + result.fixed64 = Collections.unmodifiableList(result.fixed64); + } + if (result.lengthDelimited == null) { + result.lengthDelimited = Collections.emptyList(); + } else { + result.lengthDelimited = + Collections.unmodifiableList(result.lengthDelimited); + } + if (result.group == null) { + result.group = Collections.emptyList(); + } else { + result.group = Collections.unmodifiableList(result.group); + } + + final Field returnMe = result; + result = null; + return returnMe; + } + + /** Discard the field's contents. */ + public Builder clear() { + result = new Field(); + return this; + } + + /** + * Merge the values in {@code other} into this field. For each list + * of values, {@code other}'s values are append to the ones in this + * field. + */ + public Builder mergeFrom(final Field other) { + if (!other.varint.isEmpty()) { + if (result.varint == null) { + result.varint = new ArrayList(); + } + result.varint.addAll(other.varint); + } + if (!other.fixed32.isEmpty()) { + if (result.fixed32 == null) { + result.fixed32 = new ArrayList(); + } + result.fixed32.addAll(other.fixed32); + } + if (!other.fixed64.isEmpty()) { + if (result.fixed64 == null) { + result.fixed64 = new ArrayList(); + } + result.fixed64.addAll(other.fixed64); + } + if (!other.lengthDelimited.isEmpty()) { + if (result.lengthDelimited == null) { + result.lengthDelimited = new ArrayList(); + } + result.lengthDelimited.addAll(other.lengthDelimited); + } + if (!other.group.isEmpty()) { + if (result.group == null) { + result.group = new ArrayList(); + } + result.group.addAll(other.group); + } + return this; + } + + /** Add a varint value. */ + public Builder addVarint(final long value) { + if (result.varint == null) { + result.varint = new ArrayList(); + } + result.varint.add(value); + return this; + } + + /** Add a fixed32 value. */ + public Builder addFixed32(final int value) { + if (result.fixed32 == null) { + result.fixed32 = new ArrayList(); + } + result.fixed32.add(value); + return this; + } + + /** Add a fixed64 value. */ + public Builder addFixed64(final long value) { + if (result.fixed64 == null) { + result.fixed64 = new ArrayList(); + } + result.fixed64.add(value); + return this; + } + + /** Add a length-delimited value. */ + public Builder addLengthDelimited(final ByteString value) { + if (result.lengthDelimited == null) { + result.lengthDelimited = new ArrayList(); + } + result.lengthDelimited.add(value); + return this; + } + + /** Add an embedded group. */ + public Builder addGroup(final UnknownFieldSet value) { + if (result.group == null) { + result.group = new ArrayList(); + } + result.group.add(value); + return this; + } + } + } +} diff --git a/OsmAnd-java/src/com/google/protobuf/WireFormat.java b/OsmAnd-java/src/com/google/protobuf/WireFormat.java new file mode 100644 index 0000000000..cca0b8e572 --- /dev/null +++ b/OsmAnd-java/src/com/google/protobuf/WireFormat.java @@ -0,0 +1,166 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +/** + * This class is used internally by the Protocol Buffer library and generated + * message implementations. It is public only because those generated messages + * do not reside in the {@code protobuf} package. Others should not use this + * class directly. + * + * This class contains constants and helper functions useful for dealing with + * the Protocol Buffer wire format. + * + * @author kenton@google.com Kenton Varda + */ +public final class WireFormat { + // Do not allow instantiation. + private WireFormat() {} + + static final int WIRETYPE_VARINT = 0; + static final int WIRETYPE_FIXED64 = 1; + static final int WIRETYPE_LENGTH_DELIMITED = 2; + static final int WIRETYPE_START_GROUP = 3; + static final int WIRETYPE_END_GROUP = 4; + static final int WIRETYPE_FIXED32 = 5; + // Osmand Delta change + public static final int WIRETYPE_FIXED32_LENGTH_DELIMITED = 6; + + static final int TAG_TYPE_BITS = 3; + static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; + + /** Given a tag value, determines the wire type (the lower 3 bits). */ + public static int getTagWireType(final int tag) { + return tag & TAG_TYPE_MASK; + } + + /** Given a tag value, determines the field number (the upper 29 bits). */ + public static int getTagFieldNumber(final int tag) { + return tag >>> TAG_TYPE_BITS; + } + + /** Makes a tag value given a field number and wire type. */ + static int makeTag(final int fieldNumber, final int wireType) { + return (fieldNumber << TAG_TYPE_BITS) | wireType; + } + + /** + * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is + * only here to support the lite runtime and should not be used by users. + */ + public enum JavaType { + INT(0), + LONG(0L), + FLOAT(0F), + DOUBLE(0D), + BOOLEAN(false), + STRING(""), + BYTE_STRING(ByteString.EMPTY), + ENUM(null), + MESSAGE(null); + + JavaType(final Object defaultDefault) { + this.defaultDefault = defaultDefault; + } + + /** + * The default default value for fields of this type, if it's a primitive + * type. + */ + Object getDefaultDefault() { + return defaultDefault; + } + + private final Object defaultDefault; + } + + /** + * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is + * only here to support the lite runtime and should not be used by users. + */ + public enum FieldType { + DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ), + FLOAT (JavaType.FLOAT , WIRETYPE_FIXED32 ), + INT64 (JavaType.LONG , WIRETYPE_VARINT ), + UINT64 (JavaType.LONG , WIRETYPE_VARINT ), + INT32 (JavaType.INT , WIRETYPE_VARINT ), + FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ), + FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ), + BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ), + // OSMAND FIX no methods override for enum + STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED, false), + GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP , false), + MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED , false), + BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED , false), + UINT32 (JavaType.INT , WIRETYPE_VARINT ), + ENUM (JavaType.ENUM , WIRETYPE_VARINT ), + SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ), + SFIXED64(JavaType.LONG , WIRETYPE_FIXED64 ), + SINT32 (JavaType.INT , WIRETYPE_VARINT ), + SINT64 (JavaType.LONG , WIRETYPE_VARINT ); + + FieldType(final JavaType javaType, final int wireType) { + this.javaType = javaType; + this.wireType = wireType; + this.packable = true; + } + + FieldType(final JavaType javaType, final int wireType, boolean packable) { + this.javaType = javaType; + this.wireType = wireType; + this.packable = packable; + } + + private final JavaType javaType; + private final int wireType; + private final boolean packable; + + public JavaType getJavaType() { return javaType; } + public int getWireType() { return wireType; } + + public boolean isPackable() { return true; } + } + + // Field numbers for feilds in MessageSet wire format. + static final int MESSAGE_SET_ITEM = 1; + static final int MESSAGE_SET_TYPE_ID = 2; + static final int MESSAGE_SET_MESSAGE = 3; + + // Tag numbers. + static final int MESSAGE_SET_ITEM_TAG = + makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP); + static final int MESSAGE_SET_ITEM_END_TAG = + makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP); + static final int MESSAGE_SET_TYPE_ID_TAG = + makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT); + static final int MESSAGE_SET_MESSAGE_TAG = + makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED); +} diff --git a/OsmAnd-java/src/net/osmand/CallbackWithObject.java b/OsmAnd-java/src/net/osmand/CallbackWithObject.java new file mode 100644 index 0000000000..c3651019bd --- /dev/null +++ b/OsmAnd-java/src/net/osmand/CallbackWithObject.java @@ -0,0 +1,18 @@ +package net.osmand; + +/** + * That class is designed to be common interface for callbacks with one param + * @author victor + * @param + */ +public interface CallbackWithObject { + + + /** + * Calls on processing result + * @param result could be null depends on usage + * @return processed or not + */ + public boolean processResult(T result); + +} diff --git a/OsmAnd-java/src/net/osmand/Collator.java b/OsmAnd-java/src/net/osmand/Collator.java new file mode 100644 index 0000000000..3991947b01 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/Collator.java @@ -0,0 +1,11 @@ +package net.osmand; + +/** + * Wrapper of java.text. Collator + */ +public interface Collator extends java.util.Comparator, Cloneable{ + + public boolean equals(String source, String target); + + public abstract int compare(String source, String target); +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/CollatorStringMatcher.java b/OsmAnd-java/src/net/osmand/CollatorStringMatcher.java new file mode 100644 index 0000000000..0b9419ef88 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/CollatorStringMatcher.java @@ -0,0 +1,129 @@ +package net.osmand; + + + +/** + * Abstract collator matcher that basically supports subclasses with some collator + * matching. + * + * @author pavol.zibrita + */ +public class CollatorStringMatcher implements StringMatcher { + + private final Collator collator; + private final StringMatcherMode mode; + private final String part; + + public static enum StringMatcherMode { + CHECK_ONLY_STARTS_WITH, + CHECK_STARTS_FROM_SPACE, + CHECK_STARTS_FROM_SPACE_NOT_BEGINNING, + CHECK_CONTAINS + } + + public CollatorStringMatcher(String part, StringMatcherMode mode) { + this.collator = PlatformUtil.primaryCollator(); + this.part = part; + this.mode = mode; + } + + public Collator getCollator() { + return collator; + } + + @Override + public boolean matches(String name) { + return cmatches(collator, name, part, mode); + } + + + public static boolean cmatches(Collator collator, String base, String part, StringMatcherMode mode){ + switch (mode) { + case CHECK_CONTAINS: + return ccontains(collator, base, part); + case CHECK_STARTS_FROM_SPACE: + return cstartsWith(collator, base, part, true, true); + case CHECK_STARTS_FROM_SPACE_NOT_BEGINNING: + return cstartsWith(collator, base, part, false, true); + case CHECK_ONLY_STARTS_WITH: + return cstartsWith(collator, base, part, true, false); + } + return false; + } + + + /** + * Check if part contains in base + * + * @param collator Collator to use + * @param part String to search + * @param base String where to search + * @return true if part is contained in base + */ + public static boolean ccontains(Collator collator, String base, String part) { + int pos = 0; + if (part.length() > 3) { + // improve searching by searching first 3 characters + pos = cindexOf(collator, pos, part.substring(0, 3), base); + if (pos == -1) { + return false; + } + } + pos = cindexOf(collator, pos, part, base); + if (pos == -1) { + return false; + } + return true; + } + + private static int cindexOf(Collator collator, int start, String part, String base) { + for (int pos = start; pos <= base.length() - part.length(); pos++) { + if (collator.equals(base.substring(pos, pos + part.length()), part)) { + return pos; + } + } + return -1; + } + + /** + * Checks if string starts with another string. + * Special check try to find as well in the middle of name + * + * @param collator + * @param searchIn + * @param theStart + * @return true if searchIn starts with token + */ + public static boolean cstartsWith(Collator collator, String searchIn, String theStart, + boolean checkBeginning, boolean checkSpaces) { + int startLength = theStart.length(); + int searchInLength = searchIn.length(); + if (startLength == 0) { + return true; + } + if (startLength > searchInLength) { + return false; + } + // simulate starts with for collator + if (checkBeginning) { + boolean starts = collator.equals(searchIn.substring(0, startLength), theStart); + if (starts) { + return true; + } + } + if (checkSpaces) { + for (int i = 1; i <= searchInLength - startLength; i++) { + if (isSpace(searchIn.charAt(i - 1)) && !isSpace(searchIn.charAt(i))) { + if (collator.equals(searchIn.substring(i, i + startLength), theStart)) { + return true; + } + } + } + } + return false; + } + + private static boolean isSpace(char c){ + return !Character.isLetter(c) && !Character.isDigit(c); + } +} diff --git a/OsmAnd-java/src/net/osmand/FloatMath.java b/OsmAnd-java/src/net/osmand/FloatMath.java new file mode 100644 index 0000000000..86cd9f71a5 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/FloatMath.java @@ -0,0 +1,38 @@ +package net.osmand; + +/** + * This class can be replaced with more effective on ARM devices + */ +public class FloatMath { + + public static float PI = (float) Math.PI; + + public static float cos(float a) { + return (float) Math.cos(a); + } + + public static float sin(float a) { + return (float) Math.sin(a); + } + + public static float abs(float a) { + return (float) Math.abs(a); + } + + public static float atan2(float py, float px) { + return (float) Math.atan2(py, px); + } + + public static float sqrt(float f) { + return (float) Math.sqrt(f); + } + + public static float max(float a, float b) { + if(a > b) { + return a; + } + return b; + } + + +} diff --git a/OsmAnd-java/src/net/osmand/GeoidAltitudeCorrection.java b/OsmAnd-java/src/net/osmand/GeoidAltitudeCorrection.java new file mode 100644 index 0000000000..87ec33a3ec --- /dev/null +++ b/OsmAnd-java/src/net/osmand/GeoidAltitudeCorrection.java @@ -0,0 +1,77 @@ +package net.osmand; + +import java.io.EOFException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +import org.apache.commons.logging.Log; + +public class GeoidAltitudeCorrection { + + private final Log log = PlatformUtil.getLog(GeoidAltitudeCorrection.class); + private File f; + private RandomAccessFile rf; + + private int cachedPointer = -1; + private short cachedValue = 0; + + public GeoidAltitudeCorrection(File dir) { + String[] fnames = dir.list(); + if(fnames != null) { + String fn = null; + for(String f : fnames) { + if(f.contains("WW15MGH")) { + fn = f; + break; + } + } + if (fn != null) { + this.f = new File(dir, fn); + if (f.exists()) { + try { + rf = new RandomAccessFile(f.getPath(), "r"); + } catch (FileNotFoundException e) { + log.error("Error", e); + } + } + } + } + + } + + public boolean isGeoidInformationAvailable(){ + return rf != null; + } + + public float getGeoidHeight(double lat, double lon) { + if (!isGeoidInformationAvailable()) { + return 0; + } + int shy = (int) Math.floor((90 - lat) * 4); + int shx = (int) Math.floor((lon >= 0 ? lon : lon + 360) * 4); + int pointer = ((shy * 1440) + shx) * 2; + short res = 0; + if (pointer != cachedPointer) { + try { + rf.seek(pointer); + // read short + cachedValue = readShort(); + cachedPointer = pointer; + } catch (IOException e) { + log.error("Geoid info error", e); + } + } + res = cachedValue; + return res / 100f; + } + + private short readShort() throws IOException { + byte[] b = new byte[2]; + rf.read(b); + int ch1 = b[0] < 0 ? b[0] + 256 : b[0]; + int ch2 = b[1] < 0 ? b[1] + 256 : b[1]; + return (short)((ch1 << 8) + (ch2 << 0)); + } +} diff --git a/OsmAnd-java/src/net/osmand/IProgress.java b/OsmAnd-java/src/net/osmand/IProgress.java new file mode 100644 index 0000000000..3f349573ef --- /dev/null +++ b/OsmAnd-java/src/net/osmand/IProgress.java @@ -0,0 +1,57 @@ +package net.osmand; + +/** + * That common interface that could be used by background operations. + * Implementation of it depends on chosen UI platform + */ +public interface IProgress { + + /** + * @param taskName + * @param work - -1 means that indeterminate task, + * otherwise number of could be specified + */ + public void startTask(String taskName, int work); + + public void startWork(int work); + + public void progress(int deltaWork); + + public void remaining(int remainingWork); + + public void setGeneralProgress(String genProgress); + + public void finishTask(); + + public boolean isIndeterminate(); + + public boolean isInterrupted(); + + public IProgress EMPTY_PROGRESS = new IProgress() { + + @Override + public void startWork(int work) {} + + @Override + public void startTask(String taskName, int work) {} + + @Override + public void setGeneralProgress(String genProgress) {} + + @Override + public void remaining(int remainingWork) {} + + @Override + public void progress(int deltaWork) {} + + @Override + public boolean isInterrupted() {return false;} + + @Override + public boolean isIndeterminate() {return false;} + + @Override + public void finishTask() {} + }; + +} diff --git a/OsmAnd-java/src/net/osmand/IndexConstants.java b/OsmAnd-java/src/net/osmand/IndexConstants.java new file mode 100644 index 0000000000..2f31cfd9f4 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/IndexConstants.java @@ -0,0 +1,48 @@ +package net.osmand; + + +public class IndexConstants { + + // Important : Every time you change schema of db upgrade version!!! + // If you want that new application support old index : put upgrade code in android app ResourceManager + public final static int POI_TABLE_VERSION = 1; + public final static int BINARY_MAP_VERSION = 2; // starts with 1 + public final static int VOICE_VERSION = 0; //supported download versions + public final static int TTSVOICE_VERSION = 1; //supported download versions + + public static final String POI_INDEX_EXT = ".poi.odb"; //$NON-NLS-1$ + public static final String BINARY_MAP_INDEX_EXT = ".obf"; //$NON-NLS-1$ + + public static final String GEN_LOG_EXT = ".gen.log"; //$NON-NLS-1$ + + public static final String POI_INDEX_EXT_ZIP = ".poi.zip"; //$NON-NLS-1$ + public static final String VOICE_INDEX_EXT_ZIP = ".voice.zip"; //$NON-NLS-1$ + public static final String TTSVOICE_INDEX_EXT_ZIP = ".ttsvoice.zip"; //$NON-NLS-1$ + public static final String ANYVOICE_INDEX_EXT_ZIP = "voice.zip"; //$NON-NLS-1$ //to cactch both voices, .voice.zip and .ttsvoice.zip + public static final String BINARY_MAP_INDEX_EXT_ZIP = ".obf.zip"; //$NON-NLS-1$ + + public static final String EXTRA_ZIP_EXT = ".extra.zip"; + public static final String EXTRA_EXT = ".extra"; + + public static final String RENDERER_INDEX_EXT = ".render.xml"; //$NON-NLS-1$ + + public final static String POI_TABLE = "poi"; //$NON-NLS-1$ + + public static final String INDEX_DOWNLOAD_DOMAIN = "download.osmand.net"; + public static final String APP_DIR = "osmand/"; //$NON-NLS-1$ + public static final String MAPS_PATH = ""; + public static final String BACKUP_INDEX_DIR= "backup/"; + public static final String GPX_INDEX_DIR= "tracks/"; + public static final String TILES_INDEX_DIR= "tiles/"; + public static final String SRTM_INDEX_DIR = "srtm/"; //$NON-NLS-1$ + public static final String AV_INDEX_DIR = "avnotes/"; //$NON-NLS-1$ + public static final String VOICE_INDEX_DIR = "voice/"; //$NON-NLS-1$ + public static final String RENDERERS_DIR = "rendering/"; //$NON-NLS-1$ + public static final String ROUTING_XML_FILE= "routing.xml"; + + + public static final String SQLITE_EXT = ".sqlitedb"; //$NON-NLS-1$ + public static final String TEMP_SOURCE_TO_LOAD = "temp"; + + +} diff --git a/OsmAnd-java/src/net/osmand/Location.java b/OsmAnd-java/src/net/osmand/Location.java new file mode 100644 index 0000000000..e113e3d80a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/Location.java @@ -0,0 +1,514 @@ +package net.osmand; +/* + * Copyright (C) 2007 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. + */ + + +/** + * A class representing a geographic location sensed at a particular + * time (a "fix"). A location consists of a latitude and longitude, a + * UTC timestamp. and optionally information on altitude, speed, and + * bearing. + * + *

Information specific to a particular provider or class of + * providers may be communicated to the application using getExtras, + * which returns a Bundle of key/value pairs. Each provider will only + * provide those entries for which information is available. + */ +public class Location { + + private String mProvider; + private long mTime = 0; + private double mLatitude = 0.0; + private double mLongitude = 0.0; + private boolean mHasAltitude = false; + private double mAltitude = 0.0f; + private boolean mHasSpeed = false; + private float mSpeed = 0.0f; + private boolean mHasBearing = false; + private float mBearing = 0.0f; + private boolean mHasAccuracy = false; + private float mAccuracy = 0.0f; + + // Cache the inputs and outputs of computeDistanceAndBearing + // so calls to distanceTo() and bearingTo() can share work + private double mLat1 = 0.0; + private double mLon1 = 0.0; + private double mLat2 = 0.0; + private double mLon2 = 0.0; + private float mDistance = 0.0f; + private float mInitialBearing = 0.0f; + // Scratchpad + private float[] mResults = new float[2]; + + /** + * Constructs a new Location. By default, time, latitude, + * longitude, and numSatellites are 0; hasAltitude, hasSpeed, and + * hasBearing are false; and there is no extra information. + * + * @param provider the name of the location provider that generated this + * location fix. + */ + public Location(String provider) { + mProvider = provider; + } + + /** + * Constructs a new Location object that is a copy of the given + * location. + */ + public Location(Location l) { + set(l); + } + + /** + * Sets the contents of the location to the values from the given location. + */ + public void set(Location l) { + mProvider = l.mProvider; + mTime = l.mTime; + mLatitude = l.mLatitude; + mLongitude = l.mLongitude; + mHasAltitude = l.mHasAltitude; + mAltitude = l.mAltitude; + mHasSpeed = l.mHasSpeed; + mSpeed = l.mSpeed; + mHasBearing = l.mHasBearing; + mBearing = l.mBearing; + mHasAccuracy = l.mHasAccuracy; + mAccuracy = l.mAccuracy; + } + + /** + * Clears the contents of the location. + */ + public void reset() { + mProvider = null; + mTime = 0; + mLatitude = 0; + mLongitude = 0; + mHasAltitude = false; + mAltitude = 0; + mHasSpeed = false; + mSpeed = 0; + mHasBearing = false; + mBearing = 0; + mHasAccuracy = false; + mAccuracy = 0; + } + + + private static void computeDistanceAndBearing(double lat1, double lon1, + double lat2, double lon2, float[] results) { + // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf + // using the "Inverse Formula" (section 4) + + int MAXITERS = 20; + // Convert lat/long to radians + lat1 *= Math.PI / 180.0; + lat2 *= Math.PI / 180.0; + lon1 *= Math.PI / 180.0; + lon2 *= Math.PI / 180.0; + + double a = 6378137.0; // WGS84 major axis + double b = 6356752.3142; // WGS84 semi-major axis + double f = (a - b) / a; + double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b); + + double L = lon2 - lon1; + double A = 0.0; + double U1 = Math.atan((1.0 - f) * Math.tan(lat1)); + double U2 = Math.atan((1.0 - f) * Math.tan(lat2)); + + double cosU1 = Math.cos(U1); + double cosU2 = Math.cos(U2); + double sinU1 = Math.sin(U1); + double sinU2 = Math.sin(U2); + double cosU1cosU2 = cosU1 * cosU2; + double sinU1sinU2 = sinU1 * sinU2; + + double sigma = 0.0; + double deltaSigma = 0.0; + double cosSqAlpha = 0.0; + double cos2SM = 0.0; + double cosSigma = 0.0; + double sinSigma = 0.0; + double cosLambda = 0.0; + double sinLambda = 0.0; + + double lambda = L; // initial guess + for (int iter = 0; iter < MAXITERS; iter++) { + double lambdaOrig = lambda; + cosLambda = Math.cos(lambda); + sinLambda = Math.sin(lambda); + double t1 = cosU2 * sinLambda; + double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda; + double sinSqSigma = t1 * t1 + t2 * t2; // (14) + sinSigma = Math.sqrt(sinSqSigma); + cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15) + sigma = Math.atan2(sinSigma, cosSigma); // (16) + double sinAlpha = (sinSigma == 0) ? 0.0 : + cosU1cosU2 * sinLambda / sinSigma; // (17) + cosSqAlpha = 1.0 - sinAlpha * sinAlpha; + cos2SM = (cosSqAlpha == 0) ? 0.0 : + cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18) + + double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn + A = 1 + (uSquared / 16384.0) * // (3) + (4096.0 + uSquared * + (-768 + uSquared * (320.0 - 175.0 * uSquared))); + double B = (uSquared / 1024.0) * // (4) + (256.0 + uSquared * + (-128.0 + uSquared * (74.0 - 47.0 * uSquared))); + double C = (f / 16.0) * + cosSqAlpha * + (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10) + double cos2SMSq = cos2SM * cos2SM; + deltaSigma = B * sinSigma * // (6) + (cos2SM + (B / 4.0) * + (cosSigma * (-1.0 + 2.0 * cos2SMSq) - + (B / 6.0) * cos2SM * + (-3.0 + 4.0 * sinSigma * sinSigma) * + (-3.0 + 4.0 * cos2SMSq))); + + lambda = L + + (1.0 - C) * f * sinAlpha * + (sigma + C * sinSigma * + (cos2SM + C * cosSigma * + (-1.0 + 2.0 * cos2SM * cos2SM))); // (11) + + double delta = (lambda - lambdaOrig) / lambda; + if (Math.abs(delta) < 1.0e-12) { + break; + } + } + + float distance = (float) (b * A * (sigma - deltaSigma)); + results[0] = distance; + if (results.length > 1) { + float initialBearing = (float) Math.atan2(cosU2 * sinLambda, + cosU1 * sinU2 - sinU1 * cosU2 * cosLambda); + initialBearing *= 180.0 / Math.PI; + results[1] = initialBearing; + if (results.length > 2) { + float finalBearing = (float) Math.atan2(cosU1 * sinLambda, + -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda); + finalBearing *= 180.0 / Math.PI; + results[2] = finalBearing; + } + } + } + + /** + * Computes the approximate distance in meters between two + * locations, and optionally the initial and final bearings of the + * shortest path between them. Distance and bearing are defined using the + * WGS84 ellipsoid. + * + *

The computed distance is stored in results[0]. If results has length + * 2 or greater, the initial bearing is stored in results[1]. If results has + * length 3 or greater, the final bearing is stored in results[2]. + * + * @param startLatitude the starting latitude + * @param startLongitude the starting longitude + * @param endLatitude the ending latitude + * @param endLongitude the ending longitude + * @param results an array of floats to hold the results + * + * @throws IllegalArgumentException if results is null or has length < 1 + */ + public static void distanceBetween(double startLatitude, double startLongitude, + double endLatitude, double endLongitude, float[] results) { + if (results == null || results.length < 1) { + throw new IllegalArgumentException("results is null or has length < 1"); + } + computeDistanceAndBearing(startLatitude, startLongitude, + endLatitude, endLongitude, results); + } + + /** + * Returns the approximate distance in meters between this + * location and the given location. Distance is defined using + * the WGS84 ellipsoid. + * + * @param dest the destination location + * @return the approximate distance in meters + */ + public float distanceTo(Location dest) { + // See if we already have the result + synchronized (mResults) { + if (mLatitude != mLat1 || mLongitude != mLon1 || + dest.mLatitude != mLat2 || dest.mLongitude != mLon2) { + computeDistanceAndBearing(mLatitude, mLongitude, + dest.mLatitude, dest.mLongitude, mResults); + mLat1 = mLatitude; + mLon1 = mLongitude; + mLat2 = dest.mLatitude; + mLon2 = dest.mLongitude; + mDistance = mResults[0]; + mInitialBearing = mResults[1]; + } + return mDistance; + } + } + + /** + * Returns the approximate initial bearing in degrees East of true + * North when traveling along the shortest path between this + * location and the given location. The shortest path is defined + * using the WGS84 ellipsoid. Locations that are (nearly) + * antipodal may produce meaningless results. + * + * @param dest the destination location + * @return the initial bearing in degrees + */ + public float bearingTo(Location dest) { + synchronized (mResults) { + // See if we already have the result + if (mLatitude != mLat1 || mLongitude != mLon1 || + dest.mLatitude != mLat2 || dest.mLongitude != mLon2) { + computeDistanceAndBearing(mLatitude, mLongitude, + dest.mLatitude, dest.mLongitude, mResults); + mLat1 = mLatitude; + mLon1 = mLongitude; + mLat2 = dest.mLatitude; + mLon2 = dest.mLongitude; + mDistance = mResults[0]; + mInitialBearing = mResults[1]; + } + return mInitialBearing; + } + } + + /** + * Returns the name of the provider that generated this fix, + * or null if it is not associated with a provider. + */ + public String getProvider() { + return mProvider; + } + + /** + * Sets the name of the provider that generated this fix. + */ + public void setProvider(String provider) { + mProvider = provider; + } + + /** + * Returns the UTC time of this fix, in milliseconds since January 1, + * 1970. + */ + public long getTime() { + return mTime; + } + + /** + * Sets the UTC time of this fix, in milliseconds since January 1, + * 1970. + */ + public void setTime(long time) { + mTime = time; + } + + /** + * Returns the latitude of this fix. + */ + public double getLatitude() { + return mLatitude; + } + + /** + * Sets the latitude of this fix. + */ + public void setLatitude(double latitude) { + mLatitude = latitude; + } + + /** + * Returns the longitude of this fix. + */ + public double getLongitude() { + return mLongitude; + } + + /** + * Sets the longitude of this fix. + */ + public void setLongitude(double longitude) { + mLongitude = longitude; + } + + /** + * Returns true if this fix contains altitude information, false + * otherwise. + */ + public boolean hasAltitude() { + return mHasAltitude; + } + + /** + * Returns the altitude of this fix. If {@link #hasAltitude} is false, + * 0.0f is returned. + */ + public double getAltitude() { + return mAltitude; + } + + /** + * Sets the altitude of this fix. Following this call, + * hasAltitude() will return true. + */ + public void setAltitude(double altitude) { + mAltitude = altitude; + mHasAltitude = true; + } + + /** + * Clears the altitude of this fix. Following this call, + * hasAltitude() will return false. + */ + public void removeAltitude() { + mAltitude = 0.0f; + mHasAltitude = false; + } + + /** + * Returns true if this fix contains speed information, false + * otherwise. The default implementation returns false. + */ + public boolean hasSpeed() { + return mHasSpeed; + } + + /** + * Returns the speed of the device over ground in meters/second. + * If hasSpeed() is false, 0.0f is returned. + */ + public float getSpeed() { + return mSpeed; + } + + /** + * Sets the speed of this fix, in meters/second. Following this + * call, hasSpeed() will return true. + */ + public void setSpeed(float speed) { + mSpeed = speed; + mHasSpeed = true; + } + + /** + * Clears the speed of this fix. Following this call, hasSpeed() + * will return false. + */ + public void removeSpeed() { + mSpeed = 0.0f; + mHasSpeed = false; + } + + /** + * Returns true if the provider is able to report bearing information, + * false otherwise. The default implementation returns false. + */ + public boolean hasBearing() { + return mHasBearing; + } + + /** + * Returns the direction of travel in degrees East of true + * North. If hasBearing() is false, 0.0 is returned. + */ + public float getBearing() { + return mBearing; + } + + /** + * Sets the bearing of this fix. Following this call, hasBearing() + * will return true. + */ + public void setBearing(float bearing) { + while (bearing < 0.0f) { + bearing += 360.0f; + } + while (bearing >= 360.0f) { + bearing -= 360.0f; + } + mBearing = bearing; + mHasBearing = true; + } + + /** + * Clears the bearing of this fix. Following this call, hasBearing() + * will return false. + */ + public void removeBearing() { + mBearing = 0.0f; + mHasBearing = false; + } + + /** + * Returns true if the provider is able to report accuracy information, + * false otherwise. The default implementation returns false. + */ + public boolean hasAccuracy() { + return mHasAccuracy; + } + + /** + * Returns the accuracy of the fix in meters. If hasAccuracy() is false, + * 0.0 is returned. + */ + public float getAccuracy() { + return mAccuracy; + } + + /** + * Sets the accuracy of this fix. Following this call, hasAccuracy() + * will return true. + */ + public void setAccuracy(float accuracy) { + mAccuracy = accuracy; + mHasAccuracy = true; + } + + /** + * Clears the accuracy of this fix. Following this call, hasAccuracy() + * will return false. + */ + public void removeAccuracy() { + mAccuracy = 0.0f; + mHasAccuracy = false; + } + + @Override public String toString() { + return "Location[mProvider=" + mProvider + + ",mTime=" + mTime + + ",mLatitude=" + mLatitude + + ",mLongitude=" + mLongitude + + ",mHasAltitude=" + mHasAltitude + + ",mAltitude=" + mAltitude + + ",mHasSpeed=" + mHasSpeed + + ",mSpeed=" + mSpeed + + ",mHasBearing=" + mHasBearing + + ",mBearing=" + mBearing + + ",mHasAccuracy=" + mHasAccuracy + + ",mAccuracy=" + mAccuracy; + } + + + + +} diff --git a/OsmAnd-java/src/net/osmand/NativeLibrary.java b/OsmAnd-java/src/net/osmand/NativeLibrary.java new file mode 100644 index 0000000000..5546aa008d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/NativeLibrary.java @@ -0,0 +1,289 @@ +package net.osmand; + +import gnu.trove.list.array.TIntArrayList; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.logging.Log; + +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; +import net.osmand.binary.RouteDataObject; +import net.osmand.render.RenderingRuleSearchRequest; +import net.osmand.render.RenderingRulesStorage; +import net.osmand.router.GeneralRouter; +import net.osmand.router.RouteCalculationProgress; +import net.osmand.router.RouteSegmentResult; +import net.osmand.router.RoutingConfiguration; + +public class NativeLibrary { + + public static class RenderingGenerationResult { + public RenderingGenerationResult(ByteBuffer bitmap) { + bitmapBuffer = bitmap; + } + + public final ByteBuffer bitmapBuffer; + } + + public static class NativeSearchResult { + + public long nativeHandler; + + private NativeSearchResult(long nativeHandler) { + this.nativeHandler = nativeHandler; + } + + @Override + protected void finalize() throws Throwable { + deleteNativeResult(); + super.finalize(); + } + + public void deleteNativeResult() { + if (nativeHandler != 0) { + deleteSearchResult(nativeHandler); + nativeHandler = 0; + } + } + } + + public static class NativeRouteSearchResult { + + public long nativeHandler; + public RouteDataObject[] objects; + public RouteSubregion region; + + public NativeRouteSearchResult(long nativeHandler, RouteDataObject[] objects) { + this.nativeHandler = nativeHandler; + this.objects = objects; + } + + @Override + protected void finalize() throws Throwable { + deleteNativeResult(); + super.finalize(); + } + + public void deleteNativeResult() { + if (nativeHandler != 0) { + deleteRouteSearchResult(nativeHandler); + nativeHandler = 0; + } + } + } + + /** + * @param searchResultHandle + * - must be null if there is no need to append to previous results returns native handle to results + */ + public NativeSearchResult searchObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom, + RenderingRuleSearchRequest request, boolean skipDuplicates, Object objectWithInterruptedField, String msgIfNothingFound) { + int renderRouteDataFile = 0; + if (request.searchRenderingAttribute("showRoadMapsAttribute")) { + renderRouteDataFile = request.getIntPropertyValue(request.ALL.R_ATTR_INT_VALUE); + } + return new NativeSearchResult(searchNativeObjectsForRendering(sleft, sright, stop, sbottom, zoom, request, skipDuplicates, + renderRouteDataFile, objectWithInterruptedField, msgIfNothingFound)); + } + + public RouteDataObject[] getDataObjects(NativeRouteSearchResult rs, int x31, int y31) { + if (rs.nativeHandler == 0) { + // do not throw exception because it is expected situation + return new RouteDataObject[0]; + } + return getRouteDataObjects(rs.region.routeReg, rs.nativeHandler, x31, y31); + } + + public boolean initMapFile(String filePath) { + return initBinaryMapFile(filePath); + } + + public boolean initCacheMapFile(String filePath) { + return initCacheMapFiles(filePath); + } + + public boolean closeMapFile(String filePath) { + return closeBinaryMapFile(filePath); + } + + public RouteSegmentResult[] runNativeRouting(int sx31, int sy31, int ex31, int ey31, RoutingConfiguration config, + RouteRegion[] regions, RouteCalculationProgress progress) { + TIntArrayList state = new TIntArrayList(); + List keys = new ArrayList(); + List values = new ArrayList(); + GeneralRouter r = (GeneralRouter) config.router; + fillObjects(state, keys, values, 0, r.highwaySpeed); + fillObjects(state, keys, values, 1, r.highwayPriorities); + fillObjects(state, keys, values, 2, r.avoid); + fillObjects(state, keys, values, 3, r.obstacles); + fillObjects(state, keys, values, 4, r.routingObstacles); + LinkedHashMap attrs = new LinkedHashMap(config.attributes); + attrs.putAll(r.attributes); + fillObjects(state, keys, values, 5, attrs); + + return nativeRouting(new int[] { sx31, sy31, ex31, ey31 }, state.toArray(), keys.toArray(new String[keys.size()]), + values.toArray(new String[values.size()]), config.initialDirection == null ? -360 : config.initialDirection.floatValue(), + regions, progress); + } + + public void fillObjects(TIntArrayList state, List keys, List values, int s, Map map) { + Iterator> it = map.entrySet().iterator(); + while (it.hasNext()) { + Entry n = it.next(); + state.add(s); + keys.add(n.getKey()); + values.add(n.getValue() + ""); + } + } + + public NativeRouteSearchResult loadRouteRegion(RouteSubregion sub, boolean loadObjects) { + NativeRouteSearchResult lr = loadRoutingData(sub.routeReg, sub.routeReg.getName(), sub.routeReg.getFilePointer(), sub, loadObjects); + if (lr != null && lr.nativeHandler != 0) { + lr.region = sub; + } + return lr; + } + + /**/ + protected static native NativeRouteSearchResult loadRoutingData(RouteRegion reg, String regName, int regfp, RouteSubregion subreg, + boolean loadObjects); + + protected static native void deleteRouteSearchResult(long searchResultHandle); + + protected static native RouteDataObject[] getRouteDataObjects(RouteRegion reg, long rs, int x31, int y31); + + protected static native RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig, + float initDirection, RouteRegion[] regions, RouteCalculationProgress progress); + + protected static native void deleteSearchResult(long searchResultHandle); + + protected static native boolean initBinaryMapFile(String filePath); + + protected static native boolean initCacheMapFiles(String filePath); + + protected static native boolean closeBinaryMapFile(String filePath); + + protected static native void initRenderingRulesStorage(RenderingRulesStorage storage); + + protected static native RenderingGenerationResult generateRenderingIndirect(RenderingContext rc, long searchResultHandler, + boolean isTransparent, RenderingRuleSearchRequest render, boolean encodePng); + + protected static native long searchNativeObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom, + RenderingRuleSearchRequest request, boolean skipDuplicates, int renderRouteDataFile, Object objectWithInterruptedField, + String msgIfNothingFound); + + public static native void testRoutingPing(); + + public static native int testNativeRouting(String obfPath, double sLat, double sLon, double eLat, double eLon); + + /**/ + // Empty native impl + /* + * protected static NativeRouteSearchResult loadRoutingData(RouteRegion reg, String regName, int regfp,RouteSubregion subreg, boolean + * loadObjects) { return null;} + * + * protected static void deleteRouteSearchResult(long searchResultHandle) {} + * + * protected static RouteDataObject[] getRouteDataObjects(RouteRegion reg, long rs, int x31, int y31){return null;} + * + * protected static RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig, float + * initDirection, RouteRegion[] regions, RouteCalculationProgress progress) {return null;} + * + * protected static void deleteSearchResult(long searchResultHandle) {} + * + * protected static boolean initBinaryMapFile(String filePath) {return false;} + * + * protected static boolean initCacheMapFiles(String filePath) {return false;} + * + * protected static boolean closeBinaryMapFile(String filePath) {return false;} + * + * protected static void initRenderingRulesStorage(RenderingRulesStorage storage) {} + * + * + * protected static RenderingGenerationResult generateRenderingIndirect(RenderingContext rc, long searchResultHandler, boolean + * isTransparent, RenderingRuleSearchRequest render, boolean encodePng) { return null; } + * + * protected static long searchNativeObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom, + * RenderingRuleSearchRequest request, boolean skipDuplicates, int renderRouteDataFile, Object objectWithInterruptedField, String + * msgIfNothingFound) { return 0; } + * + * public static void testRoutingPing() {} + * + * public static int testNativeRouting(String obfPath, double sLat, double sLon, double eLat, double eLon) {return 0;} /* + */ + + private static final Log log = PlatformUtil.getLog(NativeLibrary.class); + public static boolean loadAllLibs(String path) { + boolean b = true; + b &= load("Qt5Core", path); + b &= load("OsmAndCore", path); + b &= load("OsmAndCoreUtils", path); + b &= load("OsmAndJNI", path); + return b; + } + + public static boolean load(String libBaseName, String path) { + // look for a pre-installed library + if (path != null) { + try { + System.load(path + libBaseName); + return true; + } catch (UnsatisfiedLinkError e) { + log.error(e); + } // fall through + } + + // guess what a bundled library would be called + String osname = System.getProperty("os.name").toLowerCase(); + String osarch = System.getProperty("os.arch"); + if (osname.startsWith("mac os")) { + osname = "mac"; + osarch = "universal"; + } + if (osname.startsWith("windows")) + osname = "win"; + if (osname.startsWith("sunos")) + osname = "solaris"; + if (osarch.startsWith("i") && osarch.endsWith("86")) + osarch = "x86"; + String libname = libBaseName + "-" + osname + '-' + osarch + ".lib"; + + // try a bundled library + try { + ClassLoader cl = NativeLibrary.class.getClassLoader(); + InputStream in = cl.getResourceAsStream( libname); + if (in == null) { + log.error("libname: " + libname + " not found"); + return false; + } + File tmplib = File.createTempFile(libBaseName + "-", ".lib"); + tmplib.deleteOnExit(); + OutputStream out = new FileOutputStream(tmplib); + byte[] buf = new byte[1024]; + for (int len; (len = in.read(buf)) != -1;) + out.write(buf, 0, len); + in.close(); + out.close(); + + System.load(tmplib.getAbsolutePath()); + return true; + } catch (Exception e) { + e.printStackTrace(); + log.error(e.getMessage(), e); + } catch (UnsatisfiedLinkError e) { + log.error(e.getMessage(), e); + } // fall through + return false; + } +} diff --git a/OsmAnd-java/src/net/osmand/PlatformUtil.java b/OsmAnd-java/src/net/osmand/PlatformUtil.java new file mode 100644 index 0000000000..b0a56ae2ba --- /dev/null +++ b/OsmAnd-java/src/net/osmand/PlatformUtil.java @@ -0,0 +1,88 @@ +package net.osmand; + + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +/** + * That class is replacing of standard LogFactory due to + * problems with Android implementation of LogFactory. + * See Android analog of LogUtil + * + * That class should be very simple & always use LogFactory methods, + * there is an intention to delegate all static methods to LogFactory. + */ +public class PlatformUtil { + + public static boolean AVIAN_LIBRARY = false; + + public static Log getLog(Class cl){ + return LogFactory.getLog(cl); + } + + public static XmlPullParser newXMLPullParser() throws XmlPullParserException{ + return new org.kxml2.io.KXmlParser(); + } + + + // AVIAN missing dependency + /*public static net.osmand.Collator primaryCollator(){ + return new net.osmand.Collator() { + + @Override + public int compare(Object o1, Object o2) { + return compare(o1+"", o2+""); + } + + @Override + public boolean equals(String source, String target) { + if(source == null) { + return source == target; + } + return source.equals(target); + } + + @Override + public int compare(String source, String target) { + if(source == null) { + return source == target ? 0 : -1; + } + return source.compareTo(target); + } + }; + }*/ + + public static net.osmand.Collator primaryCollator(){ + final java.text.Collator instance = java.text.Collator.getInstance(); + instance.setStrength(java.text.Collator.PRIMARY); + return wrapCollator(instance); + } + + public static net.osmand.Collator wrapCollator(final java.text.Collator instance) { + return new net.osmand.Collator() { + + @Override + public int compare(Object o1, Object o2) { + return instance.compare(o1, o2); + } + + @Override + public boolean equals(Object obj) { + return instance.equals(obj); + } + + @Override + public boolean equals(String source, String target) { + return instance.equals(source, target); + } + + @Override + public int compare(String source, String target) { + return instance.compare(source, target); + } + }; + } +} diff --git a/OsmAnd-java/src/net/osmand/RenderingContext.java b/OsmAnd-java/src/net/osmand/RenderingContext.java new file mode 100644 index 0000000000..1a62b5b07b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/RenderingContext.java @@ -0,0 +1,69 @@ +package net.osmand; + + +public class RenderingContext { + static enum ShadowRenderingMode { + // int shadowRenderingMode = 0; // no shadow (minumum CPU) + // int shadowRenderingMode = 1; // classic shadow (the implementaton in master) + // int shadowRenderingMode = 2; // blur shadow (most CPU, but still reasonable) + // int shadowRenderingMode = 3; solid border (CPU use like classic version or even smaller) + NO_SHADOW(0), ONE_STEP(1), BLUR_SHADOW(2), SOLID_SHADOW(3); + public final int value; + + ShadowRenderingMode(int v) { + this.value = v; + } + } + + // FIELDS OF THAT CLASS ARE USED IN C++ + public boolean interrupted = false; + public boolean nightMode = false; + public boolean useEnglishNames = false; + public int defaultColor = 0xf1eee8; + + public RenderingContext() { + } + + + public float leftX; + public float topY; + public int width; + public int height; + + public int zoom; + public float tileDivisor; + public float rotate; + + // debug purpose + public int pointCount = 0; + public int pointInsideCount = 0; + public int visible = 0; + public int allObjects = 0; + public int textRenderingTime = 0; + public int lastRenderedKey = 0; + + // be aware field is using in C++ + public int shadowRenderingMode = ShadowRenderingMode.BLUR_SHADOW.value; + public int shadowRenderingColor = 0xff969696; + public String renderingDebugInfo; + + private float density = 1; + + public void setDensityValue(boolean highResMode, float mapTextSize, float density) { +// boolean highResMode = false; +// float mapTextSize = 1; + if (highResMode && density > 1) { + this.density = density * mapTextSize; + } else { + this.density = mapTextSize; + } + } + + public float getDensityValue(float val) { + return val * density; + } + + protected byte[] getIconRawData(String data) { + return null; + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/Reshaper.java b/OsmAnd-java/src/net/osmand/Reshaper.java new file mode 100644 index 0000000000..78c2247c13 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/Reshaper.java @@ -0,0 +1,88 @@ +package net.osmand; + +import org.apache.commons.logging.Log; + +import com.ibm.icu.text.ArabicShaping; +import com.ibm.icu.text.ArabicShapingException; +import com.ibm.icu.text.Bidi; +import com.ibm.icu.text.BidiRun; + +public class Reshaper { + private final static Log LOG = PlatformUtil.getLog(Reshaper.class); + + public static String reshape(String s) { +// if(true) { +// return s; +// } + try { + ArabicShaping as = new ArabicShaping(ArabicShaping.LETTERS_SHAPE | ArabicShaping.LENGTH_GROW_SHRINK); + try { + s = as.shape(s); + } catch (ArabicShapingException e) { + LOG.error(e.getMessage(), e); + } + Bidi line = new Bidi(s.length(), s.length()); + line.setPara(s, Bidi.LEVEL_DEFAULT_LTR, null); + byte direction = line.getDirection(); + if (direction != Bidi.MIXED) { + // unidirectional + if(line.isLeftToRight()) { + return s; + } else { + char[] chs = new char[s.length()]; + for(int i = 0; i< chs.length ; i++) { + chs[i] = s.charAt(chs.length - i - 1); + } + return new String(chs); + } + } else { + // // mixed-directional + int count = line.countRuns(); + // if (styleRunCount <= 1) { + // int style = styleRuns[0].style; + // // iterate over directional runs + // for (i = 0; i < count; ++i) { + // run = line.getVisualRun(i); + // renderRun(text, run.getStart(), run.getLimit(), + // run.getDirection(), style); + // } + // } + StringBuilder res = new StringBuilder(); + // iterate over both directional and style runs + for (int i = 0; i < count; ++i) { + BidiRun run = line.getVisualRun(i); + + int st = run.getStart(); + int e = run.getLimit(); + int j = run.getDirection() == Bidi.LTR ? st : e - 1; + int l = run.getDirection() == Bidi.LTR ? e : st - 1; + boolean plus = run.getDirection() == Bidi.LTR; + while (j != l) { + res.append(s.charAt(j)); + if (plus) { + j++; + } else { + j--; + } + } + } + return res.toString(); + } + } catch (RuntimeException e) { + LOG.error(e.getMessage(), e); + return s; + } + + } + /* + public static void main(String[] args) { +// char[] c = new char[] {'א', 'ד','ם', ' ', '1', '2'} ; +// String reshape = "אדם"; + char[] c = new char[] {'א', 'ד','ם'} ; + String reshape = reshape(new String(c)); + for(int i=0; i < reshape.length(); i++) { + System.out.println(reshape.charAt(i)); + } + }*/ + +} diff --git a/OsmAnd-java/src/net/osmand/ResultMatcher.java b/OsmAnd-java/src/net/osmand/ResultMatcher.java new file mode 100644 index 0000000000..cc36986076 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/ResultMatcher.java @@ -0,0 +1,20 @@ +package net.osmand; + +/** + * Easy matcher to be able to publish results immediately + * + */ +public interface ResultMatcher { + + /** + * @param name + * @return true if result should be added to final list + */ + boolean publish(T object); + + /** + * @returns true to stop processing + */ + boolean isCancelled(); + +} diff --git a/OsmAnd-java/src/net/osmand/StateChangedListener.java b/OsmAnd-java/src/net/osmand/StateChangedListener.java new file mode 100644 index 0000000000..f4c9e071e0 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/StateChangedListener.java @@ -0,0 +1,10 @@ +package net.osmand; + +/** + * Abstract listener represents state changed for a particular object + */ +public interface StateChangedListener { + + void stateChanged(T change); + +} diff --git a/OsmAnd-java/src/net/osmand/StringMatcher.java b/OsmAnd-java/src/net/osmand/StringMatcher.java new file mode 100644 index 0000000000..38182ed1fe --- /dev/null +++ b/OsmAnd-java/src/net/osmand/StringMatcher.java @@ -0,0 +1,17 @@ +package net.osmand; + +/** + * Easy matcher to be able to filter streets,buildings, etc.. using custom + * rules + * + * @author pavol.zibrita + */ +public interface StringMatcher { + + /** + * @param name + * @return true if this matcher matches the name String + */ + boolean matches(String name); + +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryIndexPart.java b/OsmAnd-java/src/net/osmand/binary/BinaryIndexPart.java new file mode 100644 index 0000000000..361a8fb92d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryIndexPart.java @@ -0,0 +1,32 @@ +package net.osmand.binary; + +public class BinaryIndexPart { + + String name; + int length; + int filePointer; + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getFilePointer() { + return filePointer; + } + + public void setFilePointer(int filePointer) { + this.filePointer = filePointer; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java b/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java new file mode 100644 index 0000000000..862a35cce3 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryInspector.java @@ -0,0 +1,667 @@ +package net.osmand.binary; + + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntObjectHashMap; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion; +import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock; +import net.osmand.binary.BinaryMapIndexReader.MapIndex; +import net.osmand.binary.BinaryMapIndexReader.MapRoot; +import net.osmand.binary.BinaryMapIndexReader.SearchFilter; +import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.BinaryMapIndexReader.TagValuePair; +import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.data.Building; +import net.osmand.data.City; +import net.osmand.data.MapObject; +import net.osmand.data.Street; +import net.osmand.util.MapUtils; + +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.WireFormat; + +public class BinaryInspector { + + + public static final int BUFFER_SIZE = 1 << 20; + + public static void main(String[] args) throws IOException { + inspector(args); + // test cases show info + +// inspector(new String[]{"-vaddress", "-vcities", "-vstreets", "-bbox=14.4,50.1,14.5,50.01", "/home/victor/projects/OsmAnd/data/osm-gen/Map.obf"}); + // test case extract parts + // test case + } + + private static void println(String s) { + System.out.println(s); + } + + private static void print(String s) { + System.out.print(s); + } + + protected static class VerboseInfo { + boolean vaddress; + boolean vcities; + boolean vstreetgroups; + boolean vstreets; + boolean vbuildings; + boolean vintersections; + boolean vtransport; + boolean vpoi; + boolean vmap; + boolean vmapObjects; + double lattop = 85; + double latbottom = -85; + double lonleft = -180; + double lonright = 180; + int zoom = -1; + + public boolean isVaddress() { + return vaddress; + } + + public int getZoom() { + return zoom; + } + + public boolean isVmap() { + return vmap; + } + public boolean isVpoi() { + return vpoi; + } + + public boolean isVtransport() { + return vtransport; + } + + public VerboseInfo(String[] params){ + for(int i=0;i= o.getLocation().getLatitude() && latbottom <= o.getLocation().getLatitude() + && lonleft <= o.getLocation().getLongitude() && lonright >= o.getLocation().getLongitude(); + + } + } + + public static void inspector(String[] args) throws IOException { + if(args == null || args.length == 0){ + printUsage(null); + return; + } + String f = args[0]; + if (f.charAt(0) == '-') { + // command + if (f.equals("-c") || f.equals("-combine")) { + if (args.length < 4) { + printUsage("Too few parameters to extract (require minimum 4)"); + } else { + Map parts = new HashMap(); + for (int i = 2; i < args.length; i++) { + File file = new File(args[i]); + if (!file.exists()) { + System.err.println("File to extract from doesn't exist " + args[i]); + return; + } + parts.put(file, null); + if (i < args.length - 1) { + if (args[i + 1].startsWith("-") || args[i + 1].startsWith("+")) { + parts.put(file, args[i + 1]); + i++; + } + } + } + List extracted = combineParts(new File(args[1]), parts); + if (extracted != null) { + println("\n" + extracted.size() + " parts were successfully extracted to " + args[1]); + } + } + } else if (f.startsWith("-v")) { + if (args.length < 2) { + printUsage("Missing file parameter"); + } else { + VerboseInfo vinfo = new VerboseInfo(args); + printFileInformation(args[args.length - 1], vinfo); + } + } else { + printUsage("Unknown command : " + f); + } + } else { + printFileInformation(f, null); + } + } + public static final void writeInt(CodedOutputStream ous, int v) throws IOException { + ous.writeRawByte((v >>> 24) & 0xFF); + ous.writeRawByte((v >>> 16) & 0xFF); + ous.writeRawByte((v >>> 8) & 0xFF); + ous.writeRawByte((v >>> 0) & 0xFF); + //written += 4; + } + + @SuppressWarnings("unchecked") + public static List combineParts(File fileToExtract, Map partsToExtractFrom) throws IOException { + BinaryMapIndexReader[] indexes = new BinaryMapIndexReader[partsToExtractFrom.size()]; + RandomAccessFile[] rafs = new RandomAccessFile[partsToExtractFrom.size()]; + + LinkedHashSet[] partsSet = new LinkedHashSet[partsToExtractFrom.size()]; + int c = 0; + Set addressNames = new LinkedHashSet(); + + + int version = -1; + // Go through all files and validate conistency + for(File f : partsToExtractFrom.keySet()){ + if(f.getAbsolutePath().equals(fileToExtract.getAbsolutePath())){ + System.err.println("Error : Input file is equal to output file " + f.getAbsolutePath()); + return null; + } + rafs[c] = new RandomAccessFile(f.getAbsolutePath(), "r"); + indexes[c] = new BinaryMapIndexReader(rafs[c]); + partsSet[c] = new LinkedHashSet(); + if(version == -1){ + version = indexes[c].getVersion(); + } else { + if(indexes[c].getVersion() != version){ + System.err.println("Error : Different input files has different input versions " + indexes[c].getVersion() + " != " + version); + return null; + } + } + + LinkedHashSet temp = new LinkedHashSet(); + String pattern = partsToExtractFrom.get(f); + boolean minus = true; + for (int i = 0; i < indexes[c].getIndexes().size(); i++) { + partsSet[c].add(new Float(i + 1f)); + BinaryIndexPart part = indexes[c].getIndexes().get(i); + if(part instanceof MapIndex){ + List roots = ((MapIndex) part).getRoots(); + int rsize = roots.size(); + for(int j=0; j p = partsSet[c].iterator(); + while (p.hasNext()) { + Float part = p.next(); + if (minus) { + if (temp.contains(part)) { + p.remove(); + } + } else { + if (!temp.contains(part)) { + p.remove(); + } + } + } + + c++; + } + + // write files + FileOutputStream fout = new FileOutputStream(fileToExtract); + CodedOutputStream ous = CodedOutputStream.newInstance(fout, BUFFER_SIZE); + List list = new ArrayList(); + byte[] BUFFER_TO_READ = new byte[BUFFER_SIZE]; + + ous.writeInt32(OsmandOdb.OsmAndStructure.VERSION_FIELD_NUMBER, version); + ous.writeInt64(OsmandOdb.OsmAndStructure.DATECREATED_FIELD_NUMBER, System.currentTimeMillis()); + + + for (int k = 0; k < indexes.length; k++) { + LinkedHashSet partSet = partsSet[k]; + BinaryMapIndexReader index = indexes[k]; + RandomAccessFile raf = rafs[k]; + for (int i = 0; i < index.getIndexes().size(); i++) { + if (!partSet.contains(Float.valueOf(i + 1f))) { + continue; + } + list.add(new Float(i + 1f)); + + BinaryIndexPart part = index.getIndexes().get(i); + String map; + + if (part instanceof MapIndex) { + ous.writeTag(OsmandOdb.OsmAndStructure.MAPINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); + map = "Map"; + } else if (part instanceof AddressRegion) { + ous.writeTag(OsmandOdb.OsmAndStructure.ADDRESSINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); + map = "Address"; + if (addressNames.contains(part.getName())) { + System.err.println("Error : going to merge 2 addresses with same names. Skip " + part.getName()); + continue; + } + addressNames.add(part.getName()); + } else if (part instanceof TransportIndex) { + ous.writeTag(OsmandOdb.OsmAndStructure.TRANSPORTINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); + map = "Transport"; + } else if (part instanceof PoiRegion) { + ous.writeTag(OsmandOdb.OsmAndStructure.POIINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); + map = "POI"; + } else if (part instanceof RouteRegion) { + ous.writeTag(OsmandOdb.OsmAndStructure.ROUTINGINDEX_FIELD_NUMBER, WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED); + map = "Routing"; + } else { + throw new UnsupportedOperationException(); + } + writeInt(ous, part.getLength()); + copyBinaryPart(ous, BUFFER_TO_READ, raf, part.getFilePointer(), part.getLength()); + println(MessageFormat.format("{2} part {0} is extracted {1} bytes", + new Object[]{part.getName(), part.getLength(), map})); + + } + } + + ous.writeInt32(OsmandOdb.OsmAndStructure.VERSIONCONFIRM_FIELD_NUMBER, version); + ous.flush(); + fout.close(); + + + return list; + } + + + private static void copyBinaryPart(CodedOutputStream ous, byte[] BUFFER, RandomAccessFile raf, long fp, int length) + throws IOException { + raf.seek(fp); + int toRead = length; + while (toRead > 0) { + int read = raf.read(BUFFER); + if (read == -1) { + throw new IllegalArgumentException("Unexpected end of file"); + } + if (toRead < read) { + read = toRead; + } + ous.writeRawBytes(BUFFER, 0, read); + toRead -= read; + } + } + + + protected static String formatBounds(int left, int right, int top, int bottom){ + double l = MapUtils.get31LongitudeX(left); + double r = MapUtils.get31LongitudeX(right); + double t = MapUtils.get31LatitudeY(top); + double b = MapUtils.get31LatitudeY(bottom); + return formatLatBounds(l, r, t, b); + } + + protected static String formatLatBounds(double l, double r, double t, double b){ + MessageFormat format = new MessageFormat("(left top - right bottom) : {0,number,#.####}, {1,number,#.####} NE - {2,number,#.####}, {3,number,#.####} NE", new Locale("EN", "US")); + return format.format(new Object[]{l, t, r, b}); + } + + public static void printFileInformation(String fileName,VerboseInfo verbose) throws IOException { + File file = new File(fileName); + if(!file.exists()){ + println("Binary OsmAnd index " + fileName + " was not found."); + return; + } + printFileInformation(file,verbose); + } + + + + public static void printFileInformation(File file, VerboseInfo verbose) throws IOException { + RandomAccessFile r = new RandomAccessFile(file.getAbsolutePath(), "r"); + try { + BinaryMapIndexReader index = new BinaryMapIndexReader(r); + int i = 1; + println("Binary index " + file.getName() + " version = " + index.getVersion()); + for(BinaryIndexPart p : index.getIndexes()){ + String partname = ""; + if(p instanceof MapIndex ){ + partname = "Map"; + } else if(p instanceof TransportIndex){ + partname = "Transport"; + } else if(p instanceof RouteRegion){ + partname = "Routing"; + } else if(p instanceof PoiRegion){ + partname = "Poi"; + } else if(p instanceof AddressRegion){ + partname = "Address"; + } + String name = p.getName() == null ? "" : p.getName(); + println(MessageFormat.format("{0} {1} data {3} - {2,number,#} bytes", + new Object[]{Integer.valueOf(i), partname, p.getLength(), name})); + if(p instanceof TransportIndex){ + TransportIndex ti = ((TransportIndex) p); + int sh = (31 - BinaryMapIndexReader.TRANSPORT_STOP_ZOOM); + println("\tBounds " + formatBounds(ti.getLeft() << sh, ti.getRight() << sh, + ti.getTop() << sh, ti.getBottom() << sh)); + } else if(p instanceof RouteRegion){ + RouteRegion ri = ((RouteRegion) p); + println("\tBounds " + formatLatBounds(ri.getLeftLongitude(), ri.getRightLongitude(), + ri.getTopLatitude(), ri.getBottomLatitude())); + } else if(p instanceof MapIndex){ + MapIndex m = ((MapIndex) p); + int j = 1; + for(MapRoot mi : m.getRoots()){ + println(MessageFormat.format("\t{4}.{5} Map level minZoom = {0}, maxZoom = {1}, size = {2,number,#} bytes \n\t\tBounds {3}", + new Object[] { + mi.getMinZoom(), mi.getMaxZoom(), mi.getLength(), + formatBounds(mi.getLeft(), mi.getRight(), mi.getTop(), mi.getBottom()), + i, j++})); + } + if((verbose != null && verbose.isVmap())){ + printMapDetailInfo(verbose, index, m); + } + } else if(p instanceof PoiRegion && (verbose != null && verbose.isVpoi())){ + printPOIDetailInfo(verbose, index, (PoiRegion) p); + } else if (p instanceof AddressRegion) { + List cities = ((AddressRegion) p).cities; + for (CitiesBlock c : cities) { + println("\t" + i + "." + c.type + " Address part size=" + c.length + " bytes"); + } + if (verbose != null && verbose.isVaddress()) { + printAddressDetailedInfo(verbose, index, (AddressRegion) p); + } + } + i++; + } + + + } catch (IOException e) { + System.err.println("File is not valid index : " + file.getAbsolutePath()); + throw e; + } + + } + + private static void printAddressDetailedInfo(VerboseInfo verbose, BinaryMapIndexReader index, AddressRegion region) throws IOException { + String[] cityType_String = new String[] { + "Cities/Towns section", + "Villages section", + "Postcodes section", + }; + int[] cityType = new int[] { + BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE, + BinaryMapAddressReaderAdapter.VILLAGES_TYPE, + BinaryMapAddressReaderAdapter.POSTCODES_TYPE + }; + + for (int j = 0; j < cityType.length; j++) { + int type = cityType[j]; + final List cities = index.getCities(region, null, type); + + print(MessageFormat.format("\t{0}, {1,number,#} group(s)", new Object[]{cityType_String[j], Integer.valueOf(cities.size())})); + if (BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE == type) { + if (!verbose.vstreetgroups && !verbose.vcities) { + println(""); + continue; + } + } else if (!verbose.vstreetgroups) { + println(""); + continue; + } + println(":"); + + for (City c : cities) { + int size = index.preloadStreets(c, null); + List streets = new ArrayList(c.getStreets()); + print(MessageFormat.format("\t\t''{0}'' [{1,number,#}], {2,number,#} street(s) size {3,number,#} bytes", + new Object[]{c.getEnName(), Long.valueOf(c.getId()), Integer.valueOf(streets.size()), Integer.valueOf(size)})); + if(!verbose.vstreets) + { + println(""); + continue; + } + println(":"); + if (!verbose.contains(c)) + continue; + + for (Street t : streets) { + if (!verbose.contains(t)) + continue; + index.preloadBuildings(t, null); + final List buildings = t.getBuildings(); + final List intersections = t.getIntersectedStreets(); + + println(MessageFormat.format("\t\t\t''{0}'' [{1,number,#}], {2,number,#} building(s), {3,number,#} intersections(s)", + new Object[]{t.getEnName(), Long.valueOf(t.getId()), Integer.valueOf(buildings.size()), Integer.valueOf(intersections.size())})); + + if (buildings != null && !buildings.isEmpty() && verbose.vbuildings) { + println("\t\t\t\tBuildings:"); + for (Building b : buildings) { + println(MessageFormat.format("\t\t\t\t{0} [{1,number,#}]", + new Object[]{b.getName(true), Long.valueOf(b.getId())})); + } + } + + if (intersections != null && !intersections.isEmpty() && verbose.vintersections) { + print("\t\t\t\tIntersects with:"); + for (Street s : intersections) { + println("\t\t\t\t\t" + s.getEnName()); + } + } + } + } + } + } + private static class DamnCounter + { + int value; + } + private static void printMapDetailInfo(final VerboseInfo verbose, BinaryMapIndexReader index, MapIndex mapIndex) throws IOException { + final StringBuilder b = new StringBuilder(); + final DamnCounter mapObjectsCounter = new DamnCounter(); + SearchRequest req = BinaryMapIndexReader.buildSearchRequest( + MapUtils.get31TileNumberX(verbose.lonleft), + MapUtils.get31TileNumberX(verbose.lonright), + MapUtils.get31TileNumberY(verbose.lattop), + MapUtils.get31TileNumberY(verbose.latbottom), + verbose.getZoom(), + new SearchFilter() { + @Override + public boolean accept(TIntArrayList types, MapIndex index) { + return true; + } + }, + new ResultMatcher() { + @Override + public boolean publish(BinaryMapDataObject obj) { + mapObjectsCounter.value++; + if(verbose.vmapObjects) + { + b.setLength(0); + boolean multipolygon = obj.getPolygonInnerCoordinates() != null && obj.getPolygonInnerCoordinates().length > 0; + if(multipolygon ) { + b.append("Multipolygon"); + } else { + b.append(obj.area? "Area" : (obj.getPointsLength() > 1? "Way" : "Point")); + } + int[] types = obj.getTypes(); + b.append(" types ["); + for(int j = 0; j 0) { + b.append(", "); + } + TagValuePair pair = obj.getMapIndex().decodeType(types[j]); + if(pair == null) { + System.err.println("Type " + types[j] + "was not found"); + continue; + // throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found"); + } + b.append(pair.toSimpleString()+" ("+types[j]+")"); + } + b.append("]"); + if(obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0){ + b.append(" add_types ["); + for(int j = 0; j 0) { + b.append(", "); + } + TagValuePair pair = obj.getMapIndex().decodeType(obj.getAdditionalTypes()[j]); + if(pair == null) { + System.err.println("Type " + obj.getAdditionalTypes()[j] + "was not found"); + continue; + // throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found"); + } + b.append(pair.toSimpleString()+"("+obj.getAdditionalTypes()[j]+")"); + + } + b.append("]"); + } + TIntObjectHashMap names = obj.getObjectNames(); + if(names != null && !names.isEmpty()) { + b.append(" Names ["); + int[] keys = names.keys(); + for(int j = 0; j 0) { + b.append(", "); + } + TagValuePair pair = obj.getMapIndex().decodeType(keys[j]); + if(pair == null) { + throw new NullPointerException("Type " + keys[j] + "was not found"); + } + b.append(pair.toSimpleString()+"("+keys[j]+")"); + b.append(" - ").append(names.get(keys[j])); + } + b.append("]"); + } + + b.append(" id ").append((obj.getId() >> 1)); + b.append(" lat/lon : "); + for(int i=0; i req = BinaryMapIndexReader.buildSearchPoiRequest( + MapUtils.get31TileNumberX(verbose.lonleft), + MapUtils.get31TileNumberX(verbose.lonright), + MapUtils.get31TileNumberY(verbose.lattop), + MapUtils.get31TileNumberY(verbose.latbottom), + verbose.getZoom(), + new SearchPoiTypeFilter() { + @Override + public boolean accept(AmenityType type, String subcategory) { + return true; + } + }, + new ResultMatcher() { + @Override + public boolean publish(Amenity object) { + println(object.getType().toString() + " : " + object.getSubType() + " " + object.getEnName() + " " + object.getLocation() + " id=" + (object.getId() >> 1)); + return false; + } + @Override + public boolean isCancelled() { + return false; + } + }); + + index.initCategories(p); + println("\tRegion: " + p.name); + println("\t\tBounds " + formatLatBounds(p.getLeftLongitude(), p.getRightLongitude(), + p.getTopLatitude(), p.getBottomLatitude())); + println("\t\tCategories:"); + for(int i =0; i< p.categories.size(); i++) { + println("\t\t\t" + p.categories.get(i)); + for(int j = 0; j < p.subcategories.get(i).size(); j++) + println("\t\t\t\t" + p.subcategories.get(i).get(j)); + } + req.poiTypeFilter = null;//TODO: for test only + index.searchPoi(p, req); + + } + + public static void printUsage(String warning) { + if(warning != null){ + println(warning); + } + println("Inspector is console utility for working with binary indexes of OsmAnd."); + println("It allows print info about file, extract parts and merge indexes."); + println("\nUsage for print info : inspector [-vaddress] [-vstreetgroups] [-vstreets] [-vbuildings] [-vintersections] [-vmap] [-vpoi] [-vtransport] [-zoom=Zoom] [-bbox=LeftLon,TopLat,RightLon,BottomLan] [file]"); + println(" Prints information about [file] binary index of OsmAnd."); + println(" -v.. more verbouse output (like all cities and their streets or all map objects with tags/values and coordinates)"); + println("\nUsage for combining indexes : inspector -c file_to_create (file_from_extract ((+|-)parts_to_extract)? )*"); + println("\tCreate new file of extracted parts from input file. [parts_to_extract] could be parts to include or exclude."); + println(" Example : inspector -c output_file input_file +1,2,3\n\tExtracts 1, 2, 3 parts (could be find in print info)"); + println(" Example : inspector -c output_file input_file -2,3\n\tExtracts all parts excluding 2, 3"); + println(" Example : inspector -c output_file input_file1 input_file2 input_file3\n\tSimply combine 3 files"); + println(" Example : inspector -c output_file input_file1 input_file2 -4\n\tCombine all parts of 1st file and all parts excluding 4th part of 2nd file"); + + + } + +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryInspectorNative.java b/OsmAnd-java/src/net/osmand/binary/BinaryInspectorNative.java new file mode 100644 index 0000000000..8cc8e93000 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryInspectorNative.java @@ -0,0 +1,52 @@ +package net.osmand.binary; + + +import java.io.IOException; + +import net.osmand.NativeLibrary; +import net.osmand.bridge.ObfInspector; +import net.osmand.bridge.StringVector; + +public class BinaryInspectorNative { + + + public static final int BUFFER_SIZE = 1 << 20; + + public static void main(String[] args) throws IOException { + if(args == null || args.length == 0) { + printUsage(null); + return; + } + args = new String[]{"-vmap", "-bbox=11.3,47.1,11.6,47", "/home/victor/projects/OsmAnd/data/osm-gen/Austria_2.obf"}; + // test cases show info + NativeLibrary.loadAllLibs(null); + StringVector vector = new StringVector(); + for(int i = 0; i < args.length; i++) { + vector.add(args[i]); + } + ObfInspector.inspector(vector); + } + + public static void printUsage(String warning) { + if(warning != null){ + println(warning); + } + println("Inspector is console utility for working with binary indexes of OsmAnd."); + println("It allows print info about file, extract parts and merge indexes."); + println("\nUsage for print info : inspector [-vaddress] [-vstreetgroups] [-vstreets] [-vbuildings] [-vintersections] [-vmap] [-vpoi] [-vtransport] [-zoom=Zoom] [-bbox=LeftLon,TopLat,RightLon,BottomLan] [file]"); + println(" Prints information about [file] binary index of OsmAnd."); + println(" -v.. more verbouse output (like all cities and their streets or all map objects with tags/values and coordinates)"); + println("\nUsage for combining indexes : inspector -c file_to_create (file_from_extract ((+|-)parts_to_extract)? )*"); + println("\tCreate new file of extracted parts from input file. [parts_to_extract] could be parts to include or exclude."); + println(" Example : inspector -c output_file input_file +1,2,3\n\tExtracts 1, 2, 3 parts (could be find in print info)"); + println(" Example : inspector -c output_file input_file -2,3\n\tExtracts all parts excluding 2, 3"); + println(" Example : inspector -c output_file input_file1 input_file2 input_file3\n\tSimply combine 3 files"); + println(" Example : inspector -c output_file input_file1 input_file2 -4\n\tCombine all parts of 1st file and all parts excluding 4th part of 2nd file"); + + + } + + private static void println(String string) { + System.out.println(string); + } +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java new file mode 100644 index 0000000000..0cb4222515 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java @@ -0,0 +1,593 @@ +package net.osmand.binary; + +import gnu.trove.list.array.TIntArrayList; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.osmand.CollatorStringMatcher; +import net.osmand.CollatorStringMatcher.StringMatcherMode; +import net.osmand.PlatformUtil; +import net.osmand.StringMatcher; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom; +import net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex; +import net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData; +import net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData; +import net.osmand.data.Building; +import net.osmand.data.Building.BuildingInterpolation; +import net.osmand.data.City; +import net.osmand.data.City.CityType; +import net.osmand.data.LatLon; +import net.osmand.data.MapObject; +import net.osmand.data.Street; +import net.osmand.util.MapUtils; +import net.sf.junidecode.Junidecode; + +import org.apache.commons.logging.Log; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.WireFormat; + +public class BinaryMapAddressReaderAdapter { + + public final static int CITY_TOWN_TYPE = 1; + public final static int POSTCODES_TYPE = 2; + public final static int VILLAGES_TYPE = 3; + public final static int STREET_TYPE = 4; + + private static final Log LOG = PlatformUtil.getLog(BinaryMapAddressReaderAdapter.class); + + public static class AddressRegion extends BinaryIndexPart { + String enName; + int indexNameOffset = -1; + List cities = new ArrayList(); + + LatLon calculatedCenter = null; + + public String getEnName() { + return enName; + } + + public List getCities() { + return cities; + } + + public int getIndexNameOffset() { + return indexNameOffset; + } + } + + public static class CitiesBlock extends BinaryIndexPart { + int type; + } + + private CodedInputStream codedIS; + private final BinaryMapIndexReader map; + + protected BinaryMapAddressReaderAdapter(BinaryMapIndexReader map){ + this.codedIS = map.codedIS; + this.map = map; + } + + private void skipUnknownField(int t) throws IOException { + map.skipUnknownField(t); + } + + private int readInt() throws IOException { + return map.readInt(); + } + + + protected void readAddressIndex(AddressRegion region) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + if(region.enName == null || region.enName.length() == 0){ + region.enName = Junidecode.unidecode(region.name); + } + return; + case OsmandOdb.OsmAndAddressIndex.NAME_FIELD_NUMBER : + region.name = codedIS.readString(); + break; + case OsmandOdb.OsmAndAddressIndex.NAME_EN_FIELD_NUMBER : + region.enName = codedIS.readString(); + break; + case OsmandOdb.OsmAndAddressIndex.CITIES_FIELD_NUMBER : + CitiesBlock block = new CitiesBlock(); + region.cities.add(block); + block.type = 1; + block.length = readInt(); + block.filePointer = codedIS.getTotalBytesRead(); + while(true){ + int tt = codedIS.readTag(); + int ttag = WireFormat.getTagFieldNumber(tt); + if(ttag == 0) { + break; + } else if(ttag == CitiesIndex.TYPE_FIELD_NUMBER){ + block.type = codedIS.readUInt32(); + break; + } else { + skipUnknownField(tt); + } + } + + + codedIS.seek(block.filePointer + block.length); + + break; + case OsmandOdb.OsmAndAddressIndex.NAMEINDEX_FIELD_NUMBER : + region.indexNameOffset = codedIS.getTotalBytesRead(); + int length = readInt(); + codedIS.seek(region.indexNameOffset + length + 4); + break; + default: + skipUnknownField(t); + break; + } + } + } + + protected void readCities(List cities, SearchRequest resultMatcher, StringMatcher matcher, boolean useEn) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case CitiesIndex.CITIES_FIELD_NUMBER : + int fp = codedIS.getTotalBytesRead(); + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + City c = readCityHeader(matcher, fp, useEn); + if(c != null){ + if (resultMatcher == null || resultMatcher.publish(c)) { + cities.add(c); + } + } + codedIS.popLimit(oldLimit); + if(resultMatcher != null && resultMatcher.isCancelled()){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + + protected void readCityStreets(SearchRequest resultMatcher, City city) throws IOException{ + int x = MapUtils.get31TileNumberX(city.getLocation().getLongitude()); + int y = MapUtils.get31TileNumberY(city.getLocation().getLatitude()); + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.CityBlockIndex.STREETS_FIELD_NUMBER : + Street s = new Street(city); + s.setFileOffset(codedIS.getTotalBytesRead()); + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + readStreet(s, null, false, x >> 7, y >> 7, city.isPostcode() ? city.getName() : null); + if(resultMatcher == null || resultMatcher.publish(s)){ + city.registerStreet(s); + } + if(resultMatcher != null && resultMatcher.isCancelled()) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + } + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.CityBlockIndex.BUILDINGS_FIELD_NUMBER : + // buildings for the town are not used now + skipUnknownField(t); + default: + skipUnknownField(t); + break; + } + } + } + + protected City readCityHeader(StringMatcher nameMatcher, int filePointer, boolean useEn) throws IOException{ + int x = 0; + int y = 0; + City c = null; + boolean englishNameMatched = false; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return c; + case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER : + int type = codedIS.readUInt32(); + c = new City(CityType.values()[type]); + break; + case OsmandOdb.CityIndex.ID_FIELD_NUMBER : + c.setId(codedIS.readUInt64()); + if(nameMatcher != null && useEn && !englishNameMatched){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + break; + case OsmandOdb.CityIndex.NAME_EN_FIELD_NUMBER : + String enName = codedIS.readString(); + if (nameMatcher != null && enName.length() > 0 && nameMatcher.matches(enName)) { + englishNameMatched = true; + } + c.setEnName(enName); + break; + case OsmandOdb.CityIndex.NAME_FIELD_NUMBER : + String name = codedIS.readString(); + if(nameMatcher != null){ + if(!useEn){ + if(!nameMatcher.matches(name)) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + } else if(nameMatcher.matches(Junidecode.unidecode(name))){ + englishNameMatched = true; + } + } + if(c == null) { + c = City.createPostcode(name); + } + c.setName(name); + break; + case OsmandOdb.CityIndex.X_FIELD_NUMBER : + x = codedIS.readUInt32(); + break; + case OsmandOdb.CityIndex.Y_FIELD_NUMBER : + y = codedIS.readUInt32(); + c.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x)); + if(c.getEnName().length() == 0){ + c.setEnName(Junidecode.unidecode(c.getName())); + } + break; + case OsmandOdb.CityIndex.SHIFTTOCITYBLOCKINDEX_FIELD_NUMBER : + int offset = readInt(); + offset += filePointer; + c.setFileOffset(offset); + break; + default: + skipUnknownField(t); + break; + } + } + } + + protected Street readStreet(Street s, SearchRequest buildingsMatcher, boolean loadBuildingsAndIntersected, int city24X, int city24Y, String postcodeFilter) throws IOException{ + int x = 0; + int y = 0; + boolean loadLocation = city24X != 0 || city24Y != 0; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + if(loadLocation){ + s.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x)); + } + if(s.getEnName().length() == 0){ + s.setEnName(Junidecode.unidecode(s.getName())); + } + return s; + case OsmandOdb.StreetIndex.ID_FIELD_NUMBER : + s.setId(codedIS.readUInt64()); + break; + case OsmandOdb.StreetIndex.NAME_EN_FIELD_NUMBER : + s.setEnName(codedIS.readString()); + break; + case OsmandOdb.StreetIndex.NAME_FIELD_NUMBER : + s.setName(codedIS.readString()); + break; + case OsmandOdb.StreetIndex.X_FIELD_NUMBER : + int sx = codedIS.readSInt32(); + if(loadLocation){ + x = sx + city24X; + } else { + x = (int) MapUtils.getTileNumberX(24, s.getLocation().getLongitude()); + } + break; + case OsmandOdb.StreetIndex.Y_FIELD_NUMBER : + int sy = codedIS.readSInt32(); + if(loadLocation){ + y = sy + city24Y; + } else { + y = (int) MapUtils.getTileNumberY(24, s.getLocation().getLatitude()); + } + break; + case OsmandOdb.StreetIndex.INTERSECTIONS_FIELD_NUMBER : + int length = codedIS.readRawVarint32(); + if(loadBuildingsAndIntersected){ + int oldLimit = codedIS.pushLimit(length); + Street si = readIntersectedStreet(s.getCity(), x, y); + s.addIntersectedStreet(si); + codedIS.popLimit(oldLimit); + } else { + codedIS.skipRawBytes(length); + } + break; + case OsmandOdb.StreetIndex.BUILDINGS_FIELD_NUMBER : + int offset = codedIS.getTotalBytesRead(); + length = codedIS.readRawVarint32(); + if(loadBuildingsAndIntersected){ + int oldLimit = codedIS.pushLimit(length); + Building b = readBuilding(offset, x, y); + if (postcodeFilter == null || postcodeFilter.equalsIgnoreCase(b.getPostcode())) { + if (buildingsMatcher == null || buildingsMatcher.publish(b)) { + s.addBuilding(b); + } + } + codedIS.popLimit(oldLimit); + } else { + codedIS.skipRawBytes(length); + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + protected Street readIntersectedStreet(City c, int street24X, int street24Y) throws IOException{ + int x = 0; + int y = 0; + Street s = new Street(c); + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + s.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x)); + if(s.getEnName().length() == 0){ + s.setEnName(Junidecode.unidecode(s.getName())); + } + return s; + case OsmandOdb.BuildingIndex.ID_FIELD_NUMBER : + s.setId(codedIS.readUInt64()); + break; + case OsmandOdb.StreetIntersection.NAME_EN_FIELD_NUMBER: + s.setEnName(codedIS.readString()); + break; + case OsmandOdb.StreetIntersection.NAME_FIELD_NUMBER: + s.setName(codedIS.readString()); + break; + case OsmandOdb.StreetIntersection.INTERSECTEDX_FIELD_NUMBER : + x = codedIS.readSInt32() + street24X; + break; + case OsmandOdb.StreetIntersection.INTERSECTEDY_FIELD_NUMBER : + y = codedIS.readSInt32() + street24Y; + break; + default: + skipUnknownField(t); + break; + } + } + } + + protected Building readBuilding(int fileOffset, int street24X, int street24Y) throws IOException{ + int x = 0; + int y = 0; + int x2 = 0; + int y2 = 0; + Building b = new Building(); + b.setFileOffset(fileOffset); + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + b.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x)); + if(x2 != 0 && y2 != 0) { + b.setLatLon2(new LatLon(MapUtils.getLatitudeFromTile(24, y2), MapUtils.getLongitudeFromTile(24, x2))); + } + if(b.getEnName().length() == 0){ + b.setEnName(Junidecode.unidecode(b.getName())); + } + return b; + case OsmandOdb.BuildingIndex.ID_FIELD_NUMBER : + b.setId(codedIS.readUInt64()); + break; + + case OsmandOdb.BuildingIndex.NAME_EN_FIELD_NUMBER : + b.setEnName(codedIS.readString()); + break; + case OsmandOdb.BuildingIndex.NAME_FIELD_NUMBER : + b.setName(codedIS.readString()); + break; + case OsmandOdb.BuildingIndex.NAME_EN2_FIELD_NUMBER : + // no where to set now + codedIS.readString(); + break; + case OsmandOdb.BuildingIndex.NAME2_FIELD_NUMBER : + b.setName2(codedIS.readString()); + break; + case OsmandOdb.BuildingIndex.INTERPOLATION_FIELD_NUMBER : + int sint = codedIS.readSInt32(); + if(sint > 0) { + b.setInterpolationInterval(sint); + } else { + b.setInterpolationType(BuildingInterpolation.fromValue(sint)); + } + break; + case OsmandOdb.BuildingIndex.X_FIELD_NUMBER : + x = codedIS.readSInt32() + street24X; + break; + case OsmandOdb.BuildingIndex.X2_FIELD_NUMBER : + x2 = codedIS.readSInt32() + street24X; + break; + case OsmandOdb.BuildingIndex.Y_FIELD_NUMBER : + y = codedIS.readSInt32() + street24Y; + break; + case OsmandOdb.BuildingIndex.Y2_FIELD_NUMBER : + y2 = codedIS.readSInt32() + street24Y; + break; + case OsmandOdb.BuildingIndex.POSTCODE_FIELD_NUMBER : + b.setPostcode(codedIS.readString()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + public void searchAddressDataByName(AddressRegion reg, SearchRequest req, int[] typeFilter) throws IOException { + TIntArrayList loffsets = new TIntArrayList(); + CollatorStringMatcher matcher = new CollatorStringMatcher( req.nameQuery, StringMatcherMode.CHECK_STARTS_FROM_SPACE); + long time = System.currentTimeMillis(); + int indexOffset = 0; + while (true) { + if (req.isCancelled()) { + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmAndAddressNameIndexData.TABLE_FIELD_NUMBER: + int length = readInt(); + indexOffset = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(length); + // here offsets are sorted by distance + map.readIndexedStringTable(matcher.getCollator(), req.nameQuery, "", loffsets, 0); + codedIS.popLimit(oldLimit); + break; + case OsmAndAddressNameIndexData.ATOM_FIELD_NUMBER: + // also offsets can be randomly skipped by limit + loffsets.sort(); + TIntArrayList[] refs = new TIntArrayList[5]; + for (int i = 0; i < refs.length; i++) { + refs[i] = new TIntArrayList(); + } + + LOG.info("Searched address structure in " + (System.currentTimeMillis() - time) + "ms. Found " + loffsets.size() + + " subtress"); + for (int j = 0; j < loffsets.size(); j++) { + int fp = indexOffset + loffsets.get(j); + codedIS.seek(fp); + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + int stag = 0; + do { + int st = codedIS.readTag(); + stag = WireFormat.getTagFieldNumber(st); + if(stag == AddressNameIndexData.ATOM_FIELD_NUMBER) { + int slen = codedIS.readRawVarint32(); + int soldLim = codedIS.pushLimit(slen); + readAddressNameData(req, refs, fp); + codedIS.popLimit(soldLim); + } else if(stag != 0){ + skipUnknownField(st); + } + } while(stag != 0); + + codedIS.popLimit(oldLim); + if (req.isCancelled()) { + return; + } + } + if (typeFilter == null) { + typeFilter = new int[] { CITY_TOWN_TYPE, POSTCODES_TYPE, VILLAGES_TYPE, STREET_TYPE }; + } + for (int i = 0; i < typeFilter.length && !req.isCancelled(); i++) { + TIntArrayList list = refs[typeFilter[i]]; + if (typeFilter[i] == STREET_TYPE) { + for (int j = 0; j < list.size() && !req.isCancelled(); j += 2) { + City obj = null; + { + codedIS.seek(list.get(j + 1)); + int len = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(len); + obj = readCityHeader(null, list.get(j + 1), false); + codedIS.popLimit(old); + } + if (obj != null) { + codedIS.seek(list.get(j)); + int len = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(len); + LatLon l = obj.getLocation(); + Street s = new Street(obj); + readStreet(s, null, false, MapUtils.get31TileNumberX(l.getLongitude()) >> 7, + MapUtils.get31TileNumberY(l.getLatitude()) >> 7, obj.isPostcode() ? obj.getName() : null); + + if (matcher.matches(s.getName())) { + req.publish(s); + } + codedIS.popLimit(old); + } + } + } else { + list.sort(); + for (int j = 0; j < list.size() && !req.isCancelled(); j++) { + codedIS.seek(list.get(j)); + int len = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(len); + City obj = readCityHeader(matcher, list.get(j), false); + if (obj != null) { + req.publish(obj); + } + codedIS.popLimit(old); + } + } + } + LOG.info("Whole address search by name is done in " + (System.currentTimeMillis() - time) + "ms. Found " + + req.getSearchResults().size()); + return; + default: + skipUnknownField(t); + break; + } + } + + } + + private void readAddressNameData(SearchRequest req, TIntArrayList[] refs, int fp) throws IOException { + TIntArrayList toAdd = null; + while(true){ + if(req.isCancelled()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case AddressNameIndexDataAtom.NAMEEN_FIELD_NUMBER : + codedIS.readString(); + break; + case AddressNameIndexDataAtom.NAME_FIELD_NUMBER : + codedIS.readString(); + break; + case AddressNameIndexDataAtom.SHIFTTOCITYINDEX_FIELD_NUMBER : + if(toAdd != null) { + toAdd.add(fp - codedIS.readInt32()); + } + break; + case AddressNameIndexDataAtom.SHIFTTOINDEX_FIELD_NUMBER : + if(toAdd != null) { + toAdd.add(fp - codedIS.readInt32()); + } + break; + case AddressNameIndexDataAtom.TYPE_FIELD_NUMBER : + int type = codedIS.readInt32(); + toAdd = refs[type]; + break; + default: + skipUnknownField(t); + break; + } + } + } + + +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapDataObject.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapDataObject.java new file mode 100644 index 0000000000..6032ee1e89 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapDataObject.java @@ -0,0 +1,166 @@ +package net.osmand.binary; + +import gnu.trove.map.hash.TIntObjectHashMap; +import net.osmand.binary.BinaryMapIndexReader.MapIndex; +import net.osmand.render.RenderingRulesStorage; + +public class BinaryMapDataObject { + protected int[] coordinates = null; + protected int[][] polygonInnerCoordinates = null; + protected boolean area = false; + protected int[] types = null; + protected int[] additionalTypes = null; + protected int objectType = RenderingRulesStorage.POINT_RULES; + + protected TIntObjectHashMap objectNames = null; + protected long id = 0; + + protected MapIndex mapIndex = null; + + + public BinaryMapDataObject(){ + } + + public BinaryMapDataObject(int[] coordinates, int[] types, int[][] polygonInnerCoordinates, long id){ + this.polygonInnerCoordinates = polygonInnerCoordinates; + this.coordinates = coordinates; + this.additionalTypes = new int[0]; + this.types = types; + this.id = id; + } + + protected void setCoordinates(int[] coordinates) { + this.coordinates = coordinates; + } + + public String getName(){ + if(objectNames == null){ + return ""; + } + String name = objectNames.get(mapIndex.nameEncodingType); + if(name == null){ + return ""; + } + return name; + } + + + public TIntObjectHashMap getObjectNames() { + return objectNames; + } + + public void putObjectName(int type, String name){ + if(objectNames == null){ + objectNames = new TIntObjectHashMap(); + } + objectNames.put(type, name); + } + + public int[][] getPolygonInnerCoordinates() { + return polygonInnerCoordinates; + } + + public int[] getTypes(){ + return types; + } + + public boolean containsType(int cachedType) { + if(cachedType != -1) { + for(int i=0; i map = new HashMap(); + SearchFilter sf = new SearchFilter() { + @Override + public boolean accept(TIntArrayList types, MapIndex index) { + boolean polygon = false; + boolean polyline = false; + for (int j = 0; j < types.size(); j++) { + int wholeType = types.get(j); + TagValuePair pair = index.decodeType(wholeType); + if (pair != null) { + int t = wholeType & 3; + if (t == RenderingRulesStorage.POINT_RULES) { + stat.pointCount++; + } else if (t == RenderingRulesStorage.LINE_RULES) { + stat.wayCount++; + polyline = true; + } else { + polygon = true; + stat.polygonCount++; + if (!map.containsKey(pair)) { + map.put(pair, 0); + } + map.put(pair, map.get(pair) + 1); + } + } + } + stat.totalCount++; + return polyline; + } + }; + ResultMatcher matcher = new ResultMatcher() { + TIntHashSet set = new TIntHashSet(); + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean publish(BinaryMapDataObject object) { +// double area = calculateArea(object, zoom); + double len = calculateLength(object, zoom); + if(/*tilesCovers(object, zoom, set) >= 2 && */ len > 100){ + stat.polygonBigSize ++; + if(stat.polygonBigSize % 10000 == 0){ + return true; + } + } + + return false; + } + }; + SearchRequest req = BinaryMapIndexReader.buildSearchRequest(0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, zoom, + sf, matcher); + List result = reader.searchMapIndex(req); + + ArrayList list = new ArrayList(map.keySet()); + Collections.sort(list, new Comparator() { + @Override + public int compare(TagValuePair o1, TagValuePair o2) { + return -map.get(o1) + map.get(o2); + } + + }); + for(TagValuePair tp : list){ + Integer i = map.get(tp); + if(i > 10){ +// System.out.println(tp.toString() + " " + i); + } + } + + for(BinaryMapDataObject obj : result){ + System.out.println("id " + (obj.getId() >> 3) + " " + calculateArea(obj, zoom)); + } + return stat; + } + + public static void main(String[] iargs) throws IOException { + BinaryMapIndexFilter filter = new BinaryMapIndexFilter(new File("")); + for (int i = 10; i <= 14; i++) { + Stat st = filter.process(i); + System.out.println(i + " zoom -> " + st); + } + + } + + +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java new file mode 100644 index 0000000000..e1a5ce2c7e --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapIndexReader.java @@ -0,0 +1,2109 @@ +package net.osmand.binary; + + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.TIntObjectMap; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.set.hash.TIntHashSet; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import net.osmand.Collator; +import net.osmand.CollatorStringMatcher; +import net.osmand.CollatorStringMatcher.StringMatcherMode; +import net.osmand.PlatformUtil; +import net.osmand.ResultMatcher; +import net.osmand.StringMatcher; +import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion; +import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock; +import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; +import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex; +import net.osmand.binary.OsmandOdb.MapDataBlock; +import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox; +import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule; +import net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.data.Building; +import net.osmand.data.City; +import net.osmand.data.LatLon; +import net.osmand.data.MapObject; +import net.osmand.data.Street; +import net.osmand.data.TransportRoute; +import net.osmand.data.TransportStop; +import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.WireFormat; + +public class BinaryMapIndexReader { + + public final static int TRANSPORT_STOP_ZOOM = 24; + public static final int SHIFT_COORDINATES = 5; + private final static Log log = PlatformUtil.getLog(BinaryMapIndexReader.class); + + private final RandomAccessFile raf; + /*private*/ int version; + /*private */long dateCreated; + // keep them immutable inside + /*private */ boolean basemap = false; + /*private */List mapIndexes = new ArrayList(); + /*private */List poiIndexes = new ArrayList(); + /*private */List addressIndexes = new ArrayList(); + /*private */List transportIndexes = new ArrayList(); + /*private */List routingIndexes = new ArrayList(); + /*private */List indexes = new ArrayList(); + + protected CodedInputStream codedIS; + + private final BinaryMapTransportReaderAdapter transportAdapter; + private final BinaryMapPoiReaderAdapter poiAdapter; + private final BinaryMapAddressReaderAdapter addressAdapter; + private final BinaryMapRouteReaderAdapter routeAdapter; + + private static String BASEMAP_NAME = "basemap"; + + + public BinaryMapIndexReader(final RandomAccessFile raf) throws IOException { + this.raf = raf; + codedIS = CodedInputStream.newInstance(raf); + codedIS.setSizeLimit(Integer.MAX_VALUE); // 2048 MB + transportAdapter = new BinaryMapTransportReaderAdapter(this); + addressAdapter = new BinaryMapAddressReaderAdapter(this); + poiAdapter = new BinaryMapPoiReaderAdapter(this); + routeAdapter = new BinaryMapRouteReaderAdapter(this); + init(); + } + + /*private */BinaryMapIndexReader(final RandomAccessFile raf, boolean init) throws IOException { + this.raf = raf; + codedIS = CodedInputStream.newInstance(raf); + codedIS.setSizeLimit(Integer.MAX_VALUE); // 2048 MB + transportAdapter = new BinaryMapTransportReaderAdapter(this); + addressAdapter = new BinaryMapAddressReaderAdapter(this); + poiAdapter = new BinaryMapPoiReaderAdapter(this); + routeAdapter = new BinaryMapRouteReaderAdapter(this); + if(init) { + init(); + } + } + + public BinaryMapIndexReader(final RandomAccessFile raf, BinaryMapIndexReader referenceToSameFile) throws IOException { + this.raf = raf; + codedIS = CodedInputStream.newInstance(raf); + codedIS.setSizeLimit(Integer.MAX_VALUE); // 2048 MB + version = referenceToSameFile.version; + transportAdapter = new BinaryMapTransportReaderAdapter(this); + addressAdapter = new BinaryMapAddressReaderAdapter(this); + poiAdapter = new BinaryMapPoiReaderAdapter(this); + routeAdapter = new BinaryMapRouteReaderAdapter(this); + mapIndexes = new ArrayList(referenceToSameFile.mapIndexes); + poiIndexes = new ArrayList(referenceToSameFile.poiIndexes); + addressIndexes = new ArrayList(referenceToSameFile.addressIndexes); + transportIndexes = new ArrayList(referenceToSameFile.transportIndexes); + routingIndexes = new ArrayList(referenceToSameFile.routingIndexes); + indexes = new ArrayList(referenceToSameFile.indexes); + basemap = referenceToSameFile.basemap; + } + + + public long getDateCreated() { + return dateCreated; + } + + private void init() throws IOException { + boolean initCorrectly = false; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + if(!initCorrectly){ + throw new IOException("Corrupted file. It should be ended as it starts with version"); //$NON-NLS-1$ + } + return; + case OsmandOdb.OsmAndStructure.VERSION_FIELD_NUMBER : + version = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndStructure.DATECREATED_FIELD_NUMBER : + dateCreated = codedIS.readInt64(); + break; + case OsmandOdb.OsmAndStructure.MAPINDEX_FIELD_NUMBER: + MapIndex mapIndex = new MapIndex(); + mapIndex.length = readInt(); + mapIndex.filePointer = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(mapIndex.length); + readMapIndex(mapIndex, false); + basemap = basemap || mapIndex.isBaseMap(); + codedIS.popLimit(oldLimit); + codedIS.seek(mapIndex.filePointer + mapIndex.length); + mapIndexes.add(mapIndex); + indexes.add(mapIndex); + break; + case OsmandOdb.OsmAndStructure.ADDRESSINDEX_FIELD_NUMBER: + AddressRegion region = new AddressRegion(); + region.length = readInt(); + region.filePointer = codedIS.getTotalBytesRead(); + if(addressAdapter != null){ + oldLimit = codedIS.pushLimit(region.length); + addressAdapter.readAddressIndex(region); + if(region.name != null){ + addressIndexes.add(region); + indexes.add(region); + } + codedIS.popLimit(oldLimit); + } + codedIS.seek(region.filePointer + region.length); + break; + case OsmandOdb.OsmAndStructure.TRANSPORTINDEX_FIELD_NUMBER: + TransportIndex ind = new TransportIndex(); + ind.length = readInt(); + ind.filePointer = codedIS.getTotalBytesRead(); + if (transportAdapter != null) { + oldLimit = codedIS.pushLimit(ind.length); + transportAdapter.readTransportIndex(ind); + codedIS.popLimit(oldLimit); + transportIndexes.add(ind); + indexes.add(ind); + } + codedIS.seek(ind.filePointer + ind.length); + break; + case OsmandOdb.OsmAndStructure.ROUTINGINDEX_FIELD_NUMBER: + RouteRegion routeReg = new RouteRegion(); + routeReg.length = readInt(); + routeReg.filePointer = codedIS.getTotalBytesRead(); + if (routeAdapter != null) { + oldLimit = codedIS.pushLimit(routeReg.length); + routeAdapter.readRouteIndex(routeReg); + codedIS.popLimit(oldLimit); + routingIndexes.add(routeReg); + indexes.add(routeReg); + } + codedIS.seek(routeReg.filePointer + routeReg.length); + break; + case OsmandOdb.OsmAndStructure.POIINDEX_FIELD_NUMBER: + PoiRegion poiInd = new PoiRegion(); + poiInd.length = readInt(); + poiInd.filePointer = codedIS.getTotalBytesRead(); + if (poiAdapter != null) { + oldLimit = codedIS.pushLimit(poiInd.length); + poiAdapter.readPoiIndex(poiInd, false); + codedIS.popLimit(oldLimit); + poiIndexes.add(poiInd); + indexes.add(poiInd); + } + codedIS.seek(poiInd.filePointer + poiInd.length); + break; + case OsmandOdb.OsmAndStructure.VERSIONCONFIRM_FIELD_NUMBER : + int cversion = codedIS.readUInt32(); + calculateCenterPointForRegions(); + initCorrectly = cversion == version; + break; + default: + skipUnknownField(t); + break; + } + } + } + + private void calculateCenterPointForRegions(){ + for(AddressRegion reg : addressIndexes){ + for(MapIndex map : mapIndexes){ + if(Algorithms.objectEquals(reg.name, map.name)){ + if(map.getRoots().size() > 0){ + MapRoot mapRoot = map.getRoots().get(map.getRoots().size() - 1); + double cy = (MapUtils.get31LatitudeY(mapRoot.getBottom()) + MapUtils.get31LatitudeY(mapRoot.getTop())) / 2; + double cx = (MapUtils.get31LongitudeX(mapRoot.getLeft()) + MapUtils.get31LongitudeX(mapRoot.getRight())) / 2; + reg.calculatedCenter = new LatLon(cy, cx); + break; + } + } + } + } + } + + public List getIndexes() { + return indexes; + } + + public List getMapIndexes() { + return mapIndexes; + } + + public List getRoutingIndexes() { + return routingIndexes; + } + + public boolean isBasemap() { + return basemap; + } + + public boolean containsMapData(){ + return mapIndexes.size() > 0; + } + + public boolean containsPoiData(){ + return poiIndexes.size() > 0; + } + + public boolean containsRouteData(){ + return routingIndexes.size() > 0; + } + + public boolean containsPoiData(double latitude, double longitude) { + for (PoiRegion index : poiIndexes) { + if (index.rightLongitude >= longitude && index.leftLongitude <= longitude && + index.topLatitude >= latitude && index.bottomLatitude <= latitude) { + return true; + } + } + return false; + } + + + public boolean containsPoiData(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) { + for (PoiRegion index : poiIndexes) { + if (index.rightLongitude >= leftLongitude && index.leftLongitude <= rightLongitude && + index.topLatitude >= bottomLatitude && index.bottomLatitude <= topLatitude) { + return true; + } + } + return false; + } + + public boolean containsMapData(int tile31x, int tile31y, int zoom){ + for(MapIndex mapIndex : mapIndexes){ + for(MapRoot root : mapIndex.getRoots()){ + if (root.minZoom <= zoom && root.maxZoom >= zoom) { + if (tile31x >= root.left && tile31x <= root.right && root.top <= tile31y && root.bottom >= tile31y) { + return true; + } + } + } + } + return false; + } + + public boolean containsMapData(int left31x, int top31y, int right31x, int bottom31y, int zoom){ + for(MapIndex mapIndex : mapIndexes){ + for(MapRoot root : mapIndex.getRoots()){ + if (root.minZoom <= zoom && root.maxZoom >= zoom) { + if (right31x >= root.left && left31x <= root.right && root.top <= bottom31y && root.bottom >= top31y) { + return true; + } + } + } + } + return false; + } + + public boolean containsAddressData(){ + return addressIndexes.size() > 0; + } + + public boolean hasTransportData(){ + return transportIndexes.size() > 0; + } + + + + public RandomAccessFile getRaf() { + return raf; + } + + public int readByte() throws IOException{ + byte b = codedIS.readRawByte(); + if(b < 0){ + return b + 256; + } else { + return b; + } + } + + public final int readInt() throws IOException { + int ch1 = readByte(); + int ch2 = readByte(); + int ch3 = readByte(); + int ch4 = readByte(); + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); + } + + + public int getVersion() { + return version; + } + + + + protected void skipUnknownField(int tag) throws IOException { + int wireType = WireFormat.getTagWireType(tag); + if(wireType == WireFormat.WIRETYPE_FIXED32_LENGTH_DELIMITED){ + int length = readInt(); + codedIS.skipRawBytes(length); + } else { + codedIS.skipField(tag); + } + } + + + /** + * Transport public methods + */ + public TIntObjectHashMap getTransportRoutes(int[] filePointers) throws IOException { + TIntObjectHashMap result = new TIntObjectHashMap(); + Map groupPoints = new HashMap(); + for(int filePointer : filePointers){ + TransportIndex ind = getTransportIndex(filePointer); + if (ind != null) { + if (!groupPoints.containsKey(ind)) { + groupPoints.put(ind, new TIntArrayList()); + } + groupPoints.get(ind).add(filePointer); + } + } + Iterator > it = groupPoints.entrySet().iterator(); + if(it.hasNext()){ + Entry e = it.next(); + TransportIndex ind = e.getKey(); + TIntArrayList pointers = e.getValue(); + pointers.sort(); + TIntObjectHashMap stringTable = new TIntObjectHashMap(); + for (int i = 0; i < pointers.size(); i++) { + int filePointer = pointers.get(i); + TransportRoute transportRoute = transportAdapter.getTransportRoute(filePointer, stringTable, false); + result.put(filePointer, transportRoute); + } + transportAdapter.initializeStringTable(ind, stringTable); + for(TransportRoute r : result.values(new TransportRoute[result.size()])){ + transportAdapter.initializeNames(false, r, stringTable); + } + } + return result; + } + + /** + * Transport public methods + */ + public List getTransportRouteDescriptions(TransportStop stop) throws IOException { + TransportIndex ind = getTransportIndex(stop.getFileOffset()); + if(ind == null){ + return null; + } + List list = new ArrayList(); + TIntObjectHashMap stringTable = new TIntObjectHashMap(); + for(int filePointer : stop.getReferencesToRoutes()){ + TransportRoute tr = transportAdapter.getTransportRoute(filePointer, stringTable, true); + if(tr != null){ + list.add(tr); + } + } + transportAdapter.initializeStringTable(ind, stringTable); + for(TransportRoute route : list){ + transportAdapter.initializeNames(true, route, stringTable); + } + return list; + } + + public boolean transportStopBelongsTo(TransportStop s){ + return getTransportIndex(s.getFileOffset()) != null; + } + + public List getTransportIndexes() { + return transportIndexes; + } + + private TransportIndex getTransportIndex(int filePointer) { + TransportIndex ind = null; + for(TransportIndex i : transportIndexes){ + if(i.filePointer <= filePointer && (filePointer - i.filePointer) < i.length){ + ind = i; + break; + } + } + return ind; + } + + public boolean containTransportData(double latitude, double longitude) { + double x = MapUtils.getTileNumberX(TRANSPORT_STOP_ZOOM, longitude); + double y = MapUtils.getTileNumberY(TRANSPORT_STOP_ZOOM, latitude); + for (TransportIndex index : transportIndexes) { + if (index.right >= x && index.left <= x && index.top <= y && index.bottom >= y) { + return true; + } + } + return false; + } + + public boolean containTransportData(double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude){ + double leftX = MapUtils.getTileNumberX(TRANSPORT_STOP_ZOOM, leftLongitude); + double topY = MapUtils.getTileNumberY(TRANSPORT_STOP_ZOOM, topLatitude); + double rightX = MapUtils.getTileNumberX(TRANSPORT_STOP_ZOOM, rightLongitude); + double bottomY = MapUtils.getTileNumberY(TRANSPORT_STOP_ZOOM, bottomLatitude); + for (TransportIndex index : transportIndexes) { + if (index.right >= leftX && index.left <= rightX && index.top <= bottomY && index.bottom >= topY) { + return true; + } + } + return false; + } + + public List searchTransportIndex(SearchRequest req) throws IOException { + for (TransportIndex index : transportIndexes) { + if (index.stopsFileLength == 0 || index.right < req.left || index.left > req.right || index.top > req.bottom + || index.bottom < req.top) { + continue; + } + codedIS.seek(index.stopsFileOffset); + int oldLimit = codedIS.pushLimit(index.stopsFileLength); + int offset = req.searchResults.size(); + transportAdapter.searchTransportTreeBounds(0, 0, 0, 0, req); + codedIS.popLimit(oldLimit); + if (req.stringTable != null) { + transportAdapter.initializeStringTable(index, req.stringTable); + for (int i = offset; i < req.searchResults.size(); i++) { + TransportStop st = req.searchResults.get(i); + transportAdapter.initializeNames(req.stringTable, st); + } + } + } + log.info("Search is done. Visit " + req.numberOfVisitedObjects + " objects. Read " + req.numberOfAcceptedObjects + " objects."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + log.info("Read " + req.numberOfReadSubtrees + " subtrees. Go through " + req.numberOfAcceptedSubtrees + " subtrees."); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + return req.getSearchResults(); + } + + /** + * Address public methods + */ + public List getRegionNames(){ + List names = new ArrayList(); + for(AddressRegion r : addressIndexes){ + names.add(r.name); + } + return names; + } + + public LatLon getRegionCenter(String name) { + AddressRegion rg = getRegionByName(name); + if (rg != null) { + return rg.calculatedCenter; + } + return null; + } + + private AddressRegion getRegionByName(String name){ + for(AddressRegion r : addressIndexes){ + if(r.name.equals(name)){ + return r; + } + } + throw new IllegalArgumentException(name); + } + + public List getCities(String region, SearchRequest resultMatcher, + int cityType) throws IOException { + return getCities(region, resultMatcher, null, false, cityType); + } + public List getCities(String region, SearchRequest resultMatcher, StringMatcher matcher, boolean useEn, + int cityType) throws IOException { + List cities = new ArrayList(); + AddressRegion r = getRegionByName(region); + for(CitiesBlock block : r.cities) { + if(block.type == cityType) { + codedIS.seek(block.filePointer); + int old = codedIS.pushLimit(block.length); + addressAdapter.readCities(cities, resultMatcher, matcher, useEn); + codedIS.popLimit(old); + } + } + return cities; + } + + public List getCities(AddressRegion region, SearchRequest resultMatcher, + int cityType) throws IOException { + return getCities(region, resultMatcher, null, false, cityType); + } + public List getCities(AddressRegion region, SearchRequest resultMatcher, StringMatcher matcher, boolean useEn, + int cityType) throws IOException { + List cities = new ArrayList(); + for(CitiesBlock block : region.cities) { + if(block.type == cityType) { + codedIS.seek(block.filePointer); + int old = codedIS.pushLimit(block.length); + addressAdapter.readCities(cities, resultMatcher, matcher, useEn); + codedIS.popLimit(old); + } + } + return cities; + } + + public int preloadStreets(City c, SearchRequest resultMatcher) throws IOException { + checkAddressIndex(c.getFileOffset()); + codedIS.seek(c.getFileOffset()); + int size = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(size); + addressAdapter.readCityStreets(resultMatcher, c); + codedIS.popLimit(old); + return size; + } + + private void checkAddressIndex(int offset){ + boolean ok = false; + for(AddressRegion r : addressIndexes){ + if(offset >= r.filePointer && offset <= (r.length + r.filePointer)){ + ok = true; + break; + } + } + if(!ok){ + throw new IllegalArgumentException("Illegal offset " + offset); //$NON-NLS-1$ + } + } + + public void preloadBuildings(Street s, SearchRequest resultMatcher) throws IOException { + checkAddressIndex(s.getFileOffset()); + codedIS.seek(s.getFileOffset()); + int size = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(size); + City city = s.getCity(); + addressAdapter.readStreet(s, resultMatcher, true, 0, 0, city != null && city.isPostcode() ? city.getName() : null); + codedIS.popLimit(old); + } + + + /** + * Map public methods + */ + + private void readMapIndex(MapIndex index, boolean onlyInitEncodingRules) throws IOException { + int defaultId = 1; + int oldLimit ; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + + switch (tag) { + case 0: + // encoding rules are required! + if (onlyInitEncodingRules) { + index.finishInitializingTags(); + } + return; + case OsmandOdb.OsmAndMapIndex.NAME_FIELD_NUMBER : + index.setName(codedIS.readString()); + break; + case OsmandOdb.OsmAndMapIndex.RULES_FIELD_NUMBER : + if (onlyInitEncodingRules) { + int len = codedIS.readInt32(); + oldLimit = codedIS.pushLimit(len); + readMapEncodingRule(index, defaultId++); + codedIS.popLimit(oldLimit); + } else { + skipUnknownField(t); + } + break; + case OsmandOdb.OsmAndMapIndex.LEVELS_FIELD_NUMBER : + int length = readInt(); + int filePointer = codedIS.getTotalBytesRead(); + if (!onlyInitEncodingRules) { + oldLimit = codedIS.pushLimit(length); + MapRoot mapRoot = readMapLevel(new MapRoot()); + mapRoot.length = length; + mapRoot.filePointer = filePointer; + index.getRoots().add(mapRoot); + codedIS.popLimit(oldLimit); + } + codedIS.seek(filePointer + length); + break; + default: + skipUnknownField(t); + break; + } + } + } + + + private void readMapEncodingRule(MapIndex index, int id) throws IOException { + int type = 0; + String tags = null; + String val = null; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + index.initMapEncodingRule(type, id, tags, val); + return; + case MapEncodingRule.VALUE_FIELD_NUMBER : + val = codedIS.readString().intern(); + break; + case MapEncodingRule.TAG_FIELD_NUMBER : + tags = codedIS.readString().intern(); + break; + case MapEncodingRule.TYPE_FIELD_NUMBER : + type = codedIS.readUInt32(); + break; + case MapEncodingRule.ID_FIELD_NUMBER : + id = codedIS.readUInt32(); + break; + default: + skipUnknownField(t); + break; + } + } + } + + + private MapRoot readMapLevel(MapRoot root) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return root; + case MapRootLevel.BOTTOM_FIELD_NUMBER : + root.bottom = codedIS.readInt32(); + break; + case MapRootLevel.LEFT_FIELD_NUMBER : + root.left = codedIS.readInt32(); + break; + case MapRootLevel.RIGHT_FIELD_NUMBER : + root.right = codedIS.readInt32(); + break; + case MapRootLevel.TOP_FIELD_NUMBER : + root.top = codedIS.readInt32(); + break; + case MapRootLevel.MAXZOOM_FIELD_NUMBER : + root.maxZoom = codedIS.readInt32(); + break; + case MapRootLevel.MINZOOM_FIELD_NUMBER : + root.minZoom = codedIS.readInt32(); + break; + case MapRootLevel.BOXES_FIELD_NUMBER : + int length = readInt(); + int filePointer = codedIS.getTotalBytesRead(); + if (root.trees != null) { + MapTree r = new MapTree(); + // left, ... already initialized + r.length = length; + r.filePointer = filePointer; + int oldLimit = codedIS.pushLimit(r.length); + readMapTreeBounds(r, root.left, root.right, root.top, root.bottom); + root.trees.add(r); + codedIS.popLimit(oldLimit); + } + codedIS.seek(filePointer + length); + break; + case MapRootLevel.BLOCKS_FIELD_NUMBER : + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + break; + default: + skipUnknownField(t); + break; + } + } + + } + + private void readMapTreeBounds(MapTree tree, int aleft, int aright, int atop, int abottom) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case MapDataBox.BOTTOM_FIELD_NUMBER : + tree.bottom = codedIS.readSInt32() + abottom; + break; + case MapDataBox.LEFT_FIELD_NUMBER : + tree.left = codedIS.readSInt32() + aleft; + break; + case MapDataBox.RIGHT_FIELD_NUMBER : + tree.right = codedIS.readSInt32() + aright; + break; + case MapDataBox.TOP_FIELD_NUMBER : + tree.top = codedIS.readSInt32() + atop; + break; + case MapDataBox.OCEAN_FIELD_NUMBER : + if(codedIS.readBool()) { + tree.ocean = Boolean.TRUE; + } else { + tree.ocean = Boolean.FALSE; + } + break; + case MapDataBox.SHIFTTOMAPDATA_FIELD_NUMBER : + tree.mapDataBlock = readInt() + tree.filePointer; + break; + + default: + skipUnknownField(t); + break; + } + } + } + + + + public List searchMapIndex(SearchRequest req) throws IOException { + req.numberOfVisitedObjects = 0; + req.numberOfAcceptedObjects = 0; + req.numberOfAcceptedSubtrees = 0; + req.numberOfReadSubtrees = 0; + List foundSubtrees = new ArrayList(); + for (MapIndex mapIndex : mapIndexes) { + // lazy initializing rules + if(mapIndex.encodingRules.isEmpty()) { + codedIS.seek(mapIndex.filePointer); + int oldLimit = codedIS.pushLimit(mapIndex.length); + readMapIndex(mapIndex, true); + codedIS.popLimit(oldLimit); + } + for (MapRoot index : mapIndex.getRoots()) { + if (index.minZoom <= req.zoom && index.maxZoom >= req.zoom) { + if (index.right < req.left || index.left > req.right || index.top > req.bottom || index.bottom < req.top) { + continue; + } + + // lazy initializing trees + if(index.trees == null){ + index.trees = new ArrayList(); + codedIS.seek(index.filePointer); + int oldLimit = codedIS.pushLimit(index.length); + readMapLevel(index); + codedIS.popLimit(oldLimit); + } + + for (MapTree tree : index.trees) { + if (tree.right < req.left || tree.left > req.right || tree.top > req.bottom || tree.bottom < req.top) { + continue; + } + codedIS.seek(tree.filePointer); + int oldLimit = codedIS.pushLimit(tree.length); + searchMapTreeBounds(tree, index, req, foundSubtrees); + codedIS.popLimit(oldLimit); + } + + Collections.sort(foundSubtrees, new Comparator() { + @Override + public int compare(MapTree o1, MapTree o2) { + return o1.mapDataBlock < o2.mapDataBlock ? -1 : (o1.mapDataBlock == o2.mapDataBlock ? 0 : 1); + } + }); + for(MapTree tree : foundSubtrees) { + if(!req.isCancelled()){ + codedIS.seek(tree.mapDataBlock); + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + readMapDataBlocks(req, tree, mapIndex); + codedIS.popLimit(oldLimit); + } + } + foundSubtrees.clear(); + } + + } + } + + log.info("Search is done. Visit " + req.numberOfVisitedObjects + " objects. Read " + req.numberOfAcceptedObjects + " objects."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + log.info("Read " + req.numberOfReadSubtrees + " subtrees. Go through " + req.numberOfAcceptedSubtrees + " subtrees."); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + return req.getSearchResults(); + } + + public List searchMapIndex(SearchRequest req, MapIndex mapIndex) throws IOException { + req.numberOfVisitedObjects = 0; + req.numberOfAcceptedObjects = 0; + req.numberOfAcceptedSubtrees = 0; + req.numberOfReadSubtrees = 0; + List foundSubtrees = new ArrayList(); + + // lazy initializing rules + if(mapIndex.encodingRules.isEmpty()) { + codedIS.seek(mapIndex.filePointer); + int oldLimit = codedIS.pushLimit(mapIndex.length); + readMapIndex(mapIndex, true); + codedIS.popLimit(oldLimit); + } + + for (MapRoot level : mapIndex.getRoots()) { + if ((level.minZoom <= req.zoom && level.maxZoom >= req.zoom) || req.zoom == -1) { + if (level.right < req.left || level.left > req.right || level.top > req.bottom || level.bottom < req.top) { + continue; + } + + // lazy initializing trees + if(level.trees == null){ + level.trees = new ArrayList(); + codedIS.seek(level.filePointer); + int oldLimit = codedIS.pushLimit(level.length); + readMapLevel(level); + codedIS.popLimit(oldLimit); + } + + for (MapTree tree : level.trees) { + if (tree.right < req.left || tree.left > req.right || tree.top > req.bottom || tree.bottom < req.top) { + continue; + } + codedIS.seek(tree.filePointer); + int oldLimit = codedIS.pushLimit(tree.length); + searchMapTreeBounds(tree, level, req, foundSubtrees); + codedIS.popLimit(oldLimit); + } + + Collections.sort(foundSubtrees, new Comparator() { + @Override + public int compare(MapTree o1, MapTree o2) { + return o1.mapDataBlock < o2.mapDataBlock ? -1 : (o1.mapDataBlock == o2.mapDataBlock ? 0 : 1); + } + }); + for(MapTree tree : foundSubtrees) { + if(!req.isCancelled()){ + codedIS.seek(tree.mapDataBlock); + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + readMapDataBlocks(req, tree, mapIndex); + codedIS.popLimit(oldLimit); + } + } + foundSubtrees.clear(); + } + + } + + + log.info("Search is done. Visit " + req.numberOfVisitedObjects + " objects. Read " + req.numberOfAcceptedObjects + " objects."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + log.info("Read " + req.numberOfReadSubtrees + " subtrees. Go through " + req.numberOfAcceptedSubtrees + " subtrees."); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + return req.getSearchResults(); + } + + protected void readMapDataBlocks(SearchRequest req, MapTree tree, MapIndex root) throws IOException { + List tempResults = null; + long baseId = 0; + while (true) { + if (req.isCancelled()) { + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + if(tempResults != null) { + for(BinaryMapDataObject obj : tempResults) { + req.publish(obj); + } + } + return; + case MapDataBlock.BASEID_FIELD_NUMBER: + baseId = codedIS.readUInt64(); + break; + case MapDataBlock.DATAOBJECTS_FIELD_NUMBER: + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + BinaryMapDataObject mapObject = readMapDataObject(tree, req, root); + if (mapObject != null) { + mapObject.setId(mapObject.getId() + baseId); + if (tempResults == null) { + tempResults = new ArrayList(); + } + tempResults.add(mapObject); + } + codedIS.popLimit(oldLimit); + break; + case MapDataBlock.STRINGTABLE_FIELD_NUMBER: + length = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(length); + if (tempResults != null) { + List stringTable = readStringTable(); + for (int i = 0; i < tempResults.size(); i++) { + BinaryMapDataObject rs = tempResults.get(i); + if (rs.objectNames != null) { + int[] keys = rs.objectNames.keys(); + for (int j = 0; j < keys.length; j++) { + rs.objectNames.put(keys[j], stringTable.get(rs.objectNames.get(keys[j]).charAt(0))); + } + } + } + } else { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + } + codedIS.popLimit(oldLimit); + break; + default: + skipUnknownField(t); + break; + } + } + + } + + protected void searchMapTreeBounds(MapTree current, MapTree parent, + SearchRequest req, List foundSubtrees) throws IOException { + int init = 0; + req.numberOfReadSubtrees++; + while(true){ + if(req.isCancelled()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + if(init == 0xf){ + init = 0; + // coordinates are init + if(current.right < req.left || current.left > req.right || current.top > req.bottom || current.bottom < req.top){ + return; + } else { + req.numberOfAcceptedSubtrees++; + } + } + switch (tag) { + case 0: + return; + case MapDataBox.BOTTOM_FIELD_NUMBER : + current.bottom = codedIS.readSInt32() + parent.bottom; + init |= 1; + break; + case MapDataBox.LEFT_FIELD_NUMBER : + current.left = codedIS.readSInt32() + parent.left; + init |= 2; + break; + case MapDataBox.RIGHT_FIELD_NUMBER : + current.right = codedIS.readSInt32() + parent.right; + init |= 4; + break; + case MapDataBox.TOP_FIELD_NUMBER : + current.top = codedIS.readSInt32() + parent.top; + init |= 8; + break; + case MapDataBox.SHIFTTOMAPDATA_FIELD_NUMBER : + req.numberOfAcceptedSubtrees ++; + current.mapDataBlock = readInt() + current.filePointer; + foundSubtrees.add(current); + break; + case MapDataBox.OCEAN_FIELD_NUMBER : + if(codedIS.readBool()) { + current.ocean = Boolean.TRUE; + } else { + current.ocean = Boolean.FALSE; + } + req.publishOceanTile(current.ocean); + break; + case MapDataBox.BOXES_FIELD_NUMBER : + // left, ... already initialized + MapTree child = new MapTree(); + child.length = readInt(); + child.filePointer = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(child.length); + if(current.ocean != null ){ + child.ocean = current.ocean; + } + searchMapTreeBounds(child, current, req, foundSubtrees); + codedIS.popLimit(oldLimit); + codedIS.seek(child.filePointer + child.length); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private int MASK_TO_READ = ~((1 << SHIFT_COORDINATES) - 1); + private BinaryMapDataObject readMapDataObject(MapTree tree , SearchRequest req, + MapIndex root) throws IOException { + int tag = WireFormat.getTagFieldNumber(codedIS.readTag()); + boolean area = OsmandOdb.MapData.AREACOORDINATES_FIELD_NUMBER == tag; + if(!area && OsmandOdb.MapData.COORDINATES_FIELD_NUMBER != tag) { + throw new IllegalArgumentException(); + } + req.cacheCoordinates.clear(); + int size = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(size); + int px = tree.left & MASK_TO_READ; + int py = tree.top & MASK_TO_READ; + boolean contains = false; + int minX = Integer.MAX_VALUE; + int maxX = 0; + int minY = Integer.MAX_VALUE; + int maxY = 0; + req.numberOfVisitedObjects++; + while(codedIS.getBytesUntilLimit() > 0){ + int x = (codedIS.readSInt32() << SHIFT_COORDINATES) + px; + int y = (codedIS.readSInt32() << SHIFT_COORDINATES) + py; + req.cacheCoordinates.add(x); + req.cacheCoordinates.add(y); + px = x; + py = y; + if(!contains && req.left <= x && req.right >= x && req.top <= y && req.bottom >= y){ + contains = true; + } + if(!contains){ + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + } + if(!contains){ + if(maxX >= req.left && minX <= req.right && minY <= req.bottom && maxY >= req.top){ + contains = true; + } + + } + codedIS.popLimit(old); + if(!contains){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + + // read + + List innercoordinates = null; + TIntArrayList additionalTypes = null; + TIntObjectHashMap stringNames = null; + long id = 0; + + boolean loop = true; + while (loop) { + int t = codedIS.readTag(); + tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + loop = false; + break; + case OsmandOdb.MapData.POLYGONINNERCOORDINATES_FIELD_NUMBER: + if (innercoordinates == null) { + innercoordinates = new ArrayList(); + } + TIntArrayList polygon = new TIntArrayList(); + innercoordinates.add(polygon); + px = tree.left & MASK_TO_READ; + py = tree.top & MASK_TO_READ; + size = codedIS.readRawVarint32(); + old = codedIS.pushLimit(size); + while (codedIS.getBytesUntilLimit() > 0) { + int x = (codedIS.readSInt32() << SHIFT_COORDINATES) + px; + int y = (codedIS.readSInt32() << SHIFT_COORDINATES) + py; + polygon.add(x); + polygon.add(y); + px = x; + py = y; + } + codedIS.popLimit(old); + break; + case OsmandOdb.MapData.ADDITIONALTYPES_FIELD_NUMBER: + additionalTypes = new TIntArrayList(); + int sizeL = codedIS.readRawVarint32(); + old = codedIS.pushLimit(sizeL); + while (codedIS.getBytesUntilLimit() > 0) { + additionalTypes.add(codedIS.readRawVarint32()); + } + codedIS.popLimit(old); + break; + case OsmandOdb.MapData.TYPES_FIELD_NUMBER: + req.cacheTypes.clear(); + sizeL = codedIS.readRawVarint32(); + old = codedIS.pushLimit(sizeL); + while (codedIS.getBytesUntilLimit() > 0) { + req.cacheTypes.add(codedIS.readRawVarint32()); + } + codedIS.popLimit(old); + boolean accept = true; + if (req.searchFilter != null) { + accept = req.searchFilter.accept(req.cacheTypes, root); + } + if (!accept) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + req.numberOfAcceptedObjects++; + break; + case OsmandOdb.MapData.ID_FIELD_NUMBER: + id = codedIS.readSInt64(); + break; + case OsmandOdb.MapData.STRINGNAMES_FIELD_NUMBER: + stringNames = new TIntObjectHashMap(); + sizeL = codedIS.readRawVarint32(); + old = codedIS.pushLimit(sizeL); + while (codedIS.getBytesUntilLimit() > 0) { + int stag = codedIS.readRawVarint32(); + int pId = codedIS.readRawVarint32(); + stringNames.put(stag, ((char)pId)+""); + } + codedIS.popLimit(old); + break; + default: + skipUnknownField(t); + break; + } + } +// if(req.cacheCoordinates.size() > 500 && req.cacheTypes.size() > 0) { +// TagValuePair p = root.decodeType(req.cacheTypes.get(0)); +// if("admin_level".equals(p.tag)) { +// log.info("TODO Object is ignored due to performance issues " + p.tag + " "+p.value); +// return null; +// } +// } + BinaryMapDataObject dataObject = new BinaryMapDataObject(); + dataObject.area = area; + dataObject.coordinates = req.cacheCoordinates.toArray(); + dataObject.objectNames = stringNames; + if (innercoordinates == null) { + dataObject.polygonInnerCoordinates = new int[0][0]; + } else { + dataObject.polygonInnerCoordinates = new int[innercoordinates.size()][]; + for (int i = 0; i < innercoordinates.size(); i++) { + dataObject.polygonInnerCoordinates[i] = innercoordinates.get(i).toArray(); + } + } + dataObject.types = req.cacheTypes.toArray(); + if (additionalTypes != null) { + dataObject.additionalTypes = additionalTypes.toArray(); + } else { + dataObject.additionalTypes = new int[0]; + } + dataObject.id = id; + dataObject.area = area; + dataObject.mapIndex = root; + return dataObject; + } + + public List searchAddressDataByName(SearchRequest req) throws IOException { + if (req.nameQuery == null || req.nameQuery.length() == 0) { + throw new IllegalArgumentException(); + } + for (AddressRegion reg : addressIndexes) { + if(reg.indexNameOffset != -1) { + codedIS.seek(reg.indexNameOffset); + int len = readInt(); + int old = codedIS.pushLimit(len); + addressAdapter.searchAddressDataByName(reg, req, null); + codedIS.popLimit(old); + } + } + return req.getSearchResults(); + } + + public void initCategories(PoiRegion poiIndex) throws IOException { + poiAdapter.initCategories(poiIndex); + } + + public List searchPoiByName(SearchRequest req) throws IOException { + if (req.nameQuery == null || req.nameQuery.length() == 0) { + throw new IllegalArgumentException(); + } + for (PoiRegion poiIndex : poiIndexes) { + poiAdapter.initCategories(poiIndex); + codedIS.seek(poiIndex.filePointer); + int old = codedIS.pushLimit(poiIndex.length); + poiAdapter.searchPoiByName(poiIndex, req); + codedIS.popLimit(old); + } + return req.getSearchResults(); + } + + public Map > searchPoiCategoriesByName(String query, Map > map) throws IOException { + if (query == null || query.length() == 0) { + throw new IllegalArgumentException(); + } + Collator collator = PlatformUtil.primaryCollator(); + for (PoiRegion poiIndex : poiIndexes) { + poiAdapter.initCategories(poiIndex); + for (int i = 0; i < poiIndex.categories.size(); i++) { + String cat = poiIndex.categories.get(i); + AmenityType catType = poiIndex.categoriesType.get(i); + if (CollatorStringMatcher.cmatches(collator, cat, query, StringMatcherMode.CHECK_STARTS_FROM_SPACE)) { + map.put(catType, null); + } else { + List subcats = poiIndex.subcategories.get(i); + for (int j = 0; j < subcats.size(); j++) { + if (CollatorStringMatcher.cmatches(collator, subcats.get(j), query, StringMatcherMode.CHECK_STARTS_FROM_SPACE)) { + if (!map.containsKey(catType)) { + map.put(catType, new ArrayList()); + } + List list = map.get(catType); + if (list != null) { + list.add(subcats.get(j)); + } + } + + } + } + } + } + return map; + } + + public List searchPoi(SearchRequest req) throws IOException { + req.numberOfVisitedObjects = 0; + req.numberOfAcceptedObjects = 0; + req.numberOfAcceptedSubtrees = 0; + req.numberOfReadSubtrees = 0; + for (PoiRegion poiIndex : poiIndexes) { + poiAdapter.initCategories(poiIndex); + codedIS.seek(poiIndex.filePointer); + int old = codedIS.pushLimit(poiIndex.length); + poiAdapter.searchPoiIndex(req.left, req.right, req.top, req.bottom, req, poiIndex); + codedIS.popLimit(old); + } + log.info("Read " + req.numberOfReadSubtrees + " subtrees. Go through " + req.numberOfAcceptedSubtrees + " subtrees."); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + log.info("Search poi is done. Visit " + req.numberOfVisitedObjects + " objects. Read " + req.numberOfAcceptedObjects + " objects."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + return req.getSearchResults(); + } + + public List searchPoi(PoiRegion poiIndex, SearchRequest req) throws IOException { + req.numberOfVisitedObjects = 0; + req.numberOfAcceptedObjects = 0; + req.numberOfAcceptedSubtrees = 0; + req.numberOfReadSubtrees = 0; + + poiAdapter.initCategories(poiIndex); + codedIS.seek(poiIndex.filePointer); + int old = codedIS.pushLimit(poiIndex.length); + poiAdapter.searchPoiIndex(req.left, req.right, req.top, req.bottom, req, poiIndex); + codedIS.popLimit(old); + + log.info("Read " + req.numberOfReadSubtrees + " subtrees. Go through " + req.numberOfAcceptedSubtrees + " subtrees."); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + log.info("Search poi is done. Visit " + req.numberOfVisitedObjects + " objects. Read " + req.numberOfAcceptedObjects + " objects."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + return req.getSearchResults(); + } + + protected List readStringTable() throws IOException{ + List list = new ArrayList(); + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return list; + case OsmandOdb.StringTable.S_FIELD_NUMBER : + list.add(codedIS.readString()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + + protected List getAddressIndexes() { + return addressIndexes; + } + + protected List getPoiIndexes() { + return poiIndexes; + } + + + public static SearchRequest buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter){ + return buildSearchRequest(sleft, sright, stop, sbottom, zoom, searchFilter, null); + } + + public static SearchRequest buildSearchRequest(int sleft, int sright, int stop, int sbottom, int zoom, SearchFilter searchFilter, + ResultMatcher resultMatcher){ + SearchRequest request = new SearchRequest(); + request.left = sleft; + request.right = sright; + request.top = stop; + request.bottom = sbottom; + request.zoom = zoom; + request.searchFilter = searchFilter; + request.resultMatcher = resultMatcher; + return request; + } + + public static SearchRequest buildAddressRequest(ResultMatcher resultMatcher){ + SearchRequest request = new SearchRequest(); + request.resultMatcher = resultMatcher; + return request; + } + + + + public static SearchRequest buildAddressByNameRequest(ResultMatcher resultMatcher, String nameRequest){ + SearchRequest request = new SearchRequest(); + request.resultMatcher = resultMatcher; + request.nameQuery = nameRequest; + return request; + } + + + public static SearchRequest buildSearchPoiRequest(int sleft, int sright, int stop, int sbottom, int zoom, + SearchPoiTypeFilter poiTypeFilter, ResultMatcher matcher){ + SearchRequest request = new SearchRequest(); + request.left = sleft; + request.right = sright; + request.top = stop; + request.bottom = sbottom; + request.zoom = zoom; + request.poiTypeFilter = poiTypeFilter; + request.resultMatcher = matcher; + + return request; + } + + public static SearchRequest buildSearchRouteRequest(int sleft, int sright, int stop, int sbottom, + ResultMatcher matcher){ + SearchRequest request = new SearchRequest(); + request.left = sleft; + request.right = sright; + request.top = stop; + request.bottom = sbottom; + request.resultMatcher = matcher; + + return request; + } + + public static SearchRequest buildSearchRouteBorderRequest(int sleft, int sright, int stop, int sbottom){ + SearchRequest request = new SearchRequest(); + request.left = sleft; + request.right = sright; + request.top = stop; + request.bottom = sbottom; + return request; + } + + + public static SearchRequest buildSearchPoiRequest(int x, int y, String nameFilter, int sleft, int sright, int stop, int sbottom, ResultMatcher resultMatcher){ + SearchRequest request = new SearchRequest(); + request.x = x; + request.y = y; + request.left = sleft; + request.right = sright; + request.top = stop; + request.bottom = sbottom; + request.resultMatcher = resultMatcher; + request.nameQuery = nameFilter; + return request; + } + + + public static SearchRequest buildSearchTransportRequest(int sleft, int sright, int stop, int sbottom, int limit, List stops){ + SearchRequest request = new SearchRequest(); + if (stops != null) { + request.searchResults = stops; + } + request.stringTable = new TIntObjectHashMap(); + request.left = sleft >> (31 - TRANSPORT_STOP_ZOOM); + request.right = sright >> (31 - TRANSPORT_STOP_ZOOM); + request.top = stop >> (31 - TRANSPORT_STOP_ZOOM); + request.bottom = sbottom >> (31 - TRANSPORT_STOP_ZOOM); + request.limit = limit; + return request; + } + + public void close() throws IOException{ + if(codedIS != null){ + raf.close(); + codedIS = null; + mapIndexes.clear(); + addressIndexes.clear(); + transportIndexes.clear(); + } + } + + public static interface SearchFilter { + + public boolean accept(TIntArrayList types, MapIndex index); + + } + + public static interface SearchPoiTypeFilter { + + public boolean accept(AmenityType type, String subcategory); + + } + + public static class SearchRequest { + private List searchResults = new ArrayList(); + private boolean land = false; + private boolean ocean = false; + + private ResultMatcher resultMatcher; + + // 31 zoom tiles + // common variables + int x = 0; + int y = 0; + int left = 0; + int right = 0; + int top = 0; + int bottom = 0; + + int zoom = 15; + int limit = -1; + + + String nameQuery = null; + + SearchFilter searchFilter = null; + + SearchPoiTypeFilter poiTypeFilter = null; + + // internal read information + TIntObjectHashMap stringTable = null; + + // cache information + TIntArrayList cacheCoordinates = new TIntArrayList(); + TIntArrayList cacheTypes = new TIntArrayList(); + + + // TRACE INFO + int numberOfVisitedObjects = 0; + int numberOfAcceptedObjects = 0; + int numberOfReadSubtrees = 0; + int numberOfAcceptedSubtrees = 0; + boolean interrupted = false; + + protected SearchRequest(){ + } + + + public boolean publish(T obj){ + if(resultMatcher == null || resultMatcher.publish(obj)){ + searchResults.add(obj); + return true; + } + return false; + } + + protected void publishOceanTile(boolean ocean){ + if(ocean) { + this.ocean = true; + } else { + this.land = true; + } + } + + public List getSearchResults() { + return searchResults; + } + + public void setInterrupted(boolean interrupted) { + this.interrupted = interrupted; + } + + public boolean limitExceeded() { + return limit != -1 && searchResults.size() > limit; + } + public boolean isCancelled() { + if(this.interrupted){ + return interrupted; + } + if(resultMatcher != null){ + return resultMatcher.isCancelled(); + } + return false; + } + + public boolean isOcean() { + return ocean; + } + + public boolean isLand() { + return land; + } + + public boolean intersects(int l, int t, int r, int b){ + return r >= left && l <= right && t <= bottom && b >= top; + } + + public boolean contains(int l, int t, int r, int b){ + return r <= right && l >= left && b <= bottom && t >= top; + } + + public int getLeft() { + return left; + } + + public int getRight() { + return right; + } + + public int getBottom() { + return bottom; + } + + public int getTop() { + return top; + } + + public void clearSearchResults(){ + // recreate whole list to allow GC collect old data + searchResults = new ArrayList(); + cacheCoordinates.clear(); + cacheTypes.clear(); + land = false; + ocean = false; + numberOfVisitedObjects = 0; + numberOfAcceptedObjects = 0; + numberOfReadSubtrees = 0; + numberOfAcceptedSubtrees = 0; + } + } + + + public static class MapIndex extends BinaryIndexPart { + List roots = new ArrayList(); + + Map > encodingRules = new HashMap >(); + TIntObjectMap decodingRules = new TIntObjectHashMap(); + public int nameEncodingType = 0; + public int refEncodingType = -1; + public int coastlineEncodingType = -1; + public int coastlineBrokenEncodingType = -1; + public int landEncodingType = -1; + public int onewayAttribute = -1; + public int onewayReverseAttribute = -1; + public TIntHashSet positiveLayers = new TIntHashSet(2); + public TIntHashSet negativeLayers = new TIntHashSet(2); + + public Integer getRule(String t, String v){ + Map m = encodingRules.get(t); + if(m != null){ + return m.get(v); + } + return null; + } + + public List getRoots() { + return roots; + } + + public TagValuePair decodeType(int type){ + return decodingRules.get(type); + } + + public void finishInitializingTags() { + int free = decodingRules.size() * 2 + 1; + coastlineBrokenEncodingType = free++; + initMapEncodingRule(0, coastlineBrokenEncodingType, "natural", "coastline_broken"); + if(landEncodingType == -1){ + landEncodingType = free++; + initMapEncodingRule(0, landEncodingType, "natural", "land"); + } + } + + public void initMapEncodingRule(int type, int id, String tag, String val) { + if(!encodingRules.containsKey(tag)){ + encodingRules.put(tag, new HashMap()); + } + encodingRules.get(tag).put(val, id); + if(!decodingRules.containsKey(id)){ + decodingRules.put(id, new TagValuePair(tag, val, type)); + } + + if("name".equals(tag)){ + nameEncodingType = id; + } else if("natural".equals(tag) && "coastline".equals(val)){ + coastlineEncodingType = id; + } else if("natural".equals(tag) && "land".equals(val)){ + landEncodingType = id; + } else if("oneway".equals(tag) && "yes".equals(val)){ + onewayAttribute = id; + } else if("oneway".equals(tag) && "-1".equals(val)){ + onewayReverseAttribute = id; + } else if("ref".equals(tag)){ + refEncodingType = id; + } else if("tunnel".equals(tag)){ + negativeLayers.add(id); + } else if("bridge".equals(tag)){ + positiveLayers.add(id); + } else if("layer".equals(tag)){ + if(val != null && !val.equals("0") && val.length() > 0) { + if(val.startsWith("-")) { + negativeLayers.add(id); + } else { + positiveLayers.add(id); + } + } + } + } + + public boolean isBaseMap(){ + return name != null && name.toLowerCase().contains(BASEMAP_NAME); + } + } + + public static class TagValuePair { + public String tag; + public String value; + public int additionalAttribute; + + + public TagValuePair(String tag, String value, int additionalAttribute) { + super(); + this.tag = tag; + this.value = value; + this.additionalAttribute = additionalAttribute; + } + + public boolean isAdditional(){ + return additionalAttribute % 2 == 1; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + additionalAttribute; + result = prime * result + ((tag == null) ? 0 : tag.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + public String toSimpleString(){ + if(value == null){ + return tag; + } + return tag+"-"+value; + } + + @Override + public String toString() { + return "TagValuePair : " + tag + " - " + value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TagValuePair other = (TagValuePair) obj; + if (additionalAttribute != other.additionalAttribute) + return false; + if (tag == null) { + if (other.tag != null) + return false; + } else if (!tag.equals(other.tag)) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + } + + + public static class MapRoot extends MapTree { + int minZoom = 0; + int maxZoom = 0; + + + public int getMinZoom() { + return minZoom; + } + public int getMaxZoom() { + return maxZoom; + } + + private List trees = null; + } + + private static class MapTree { + int filePointer = 0; + int length = 0; + + long mapDataBlock = 0; + Boolean ocean = null; + + int left = 0; + int right = 0; + int top = 0; + int bottom = 0; + + public int getLeft() { + return left; + } + public int getRight() { + return right; + } + public int getTop() { + return top; + } + public int getBottom() { + return bottom; + } + + public int getLength() { + return length; + } + public int getFilePointer() { + return filePointer; + } + + @Override + public String toString(){ + return "Top Lat " + ((float) MapUtils.get31LatitudeY(top)) + " lon " + ((float) MapUtils.get31LongitudeX(left)) + + " Bottom lat " + ((float) MapUtils.get31LatitudeY(bottom)) + " lon " + ((float) MapUtils.get31LongitudeX(right)); + } + + } + + + private static boolean testMapSearch = true; + private static boolean testAddressSearch = false; + private static boolean testPoiSearch = false; + private static boolean testTransportSearch = false; + private static int sleft = MapUtils.get31TileNumberX(6.3); + private static int sright = MapUtils.get31TileNumberX(6.5); + private static int stop = MapUtils.get31TileNumberY(49.9); + private static int sbottom = MapUtils.get31TileNumberY(49.7); + private static int szoom = 15; + + private static void println(String s){ + System.out.println(s); + } + + public static void main(String[] args) throws IOException { + RandomAccessFile raf = new RandomAccessFile("", "r"); + + BinaryMapIndexReader reader = new BinaryMapIndexReader(raf); + println("VERSION " + reader.getVersion()); //$NON-NLS-1$ + long time = System.currentTimeMillis(); + + if (testMapSearch) { + testMapSearch(reader); + } + if(testAddressSearch) { + testAddressSearchByName(reader); + testAddressSearch(reader); + } + if(testTransportSearch) { + testTransportSearch(reader); + } + + if (testPoiSearch) { + PoiRegion poiRegion = reader.getPoiIndexes().get(0); + testPoiSearch(reader, poiRegion); + testPoiSearchByName(reader); + } + + println("MEMORY " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //$NON-NLS-1$ + println("Time " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ + } + + private static void testPoiSearchByName(BinaryMapIndexReader reader) throws IOException { + println("Searching by name..."); + int tileZ = 31 - 14; + SearchRequest req = buildSearchPoiRequest(sleft/2+sright/2, stop/2+sbottom/2, "kol", + sleft - 1< req = buildSearchPoiRequest(sleft, sright, stop, sbottom, -1, new SearchPoiTypeFilter() { + @Override + public boolean accept(AmenityType type, String subcategory) { +// return type == AmenityType.TRANSPORTATION && "fuel".equals(subcategory); + return true; + } + }, null); + List results = reader.searchPoi(req); + for (Amenity a : results) { + println(a.getType() + " " + a.getSubType() + " " + a.getName() + " " + a.getLocation()); + } + } + + private static void testTransportSearch(BinaryMapIndexReader reader) throws IOException { + // test transport + for (TransportIndex i : reader.transportIndexes) { + println("Transport bounds : " + i.left + " " + i.right + " " + i.top + " " + i.bottom); + } + { + for (TransportStop s : reader.searchTransportIndex(buildSearchTransportRequest(sleft, sright, stop, sbottom, 15, null))) { + println(s.getName()); + TIntObjectHashMap routes = reader.getTransportRoutes(s.getReferencesToRoutes()); + for (net.osmand.data.TransportRoute route : routes.valueCollection()) { + println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " " + + route.getAvgBothDistance()); + } + } + } + { + for (TransportStop s : reader.searchTransportIndex(buildSearchTransportRequest(sleft, sright, stop, sbottom, 16, null))) { + println(s.getName()); + TIntObjectHashMap routes = reader.getTransportRoutes(s.getReferencesToRoutes()); + for (net.osmand.data.TransportRoute route : routes.valueCollection()) { + println(" " + route.getRef() + " " + route.getName() + " " + route.getDistance() + " " + + route.getAvgBothDistance()); + } + } + } + } + + private static void updateFrequence(Map street , String key){ + if(!street.containsKey(key)){ + street.put(key, 1); + } else { + street.put(key, street.get(key) + 1); + } + + } + + int readIndexedStringTable(Collator instance, String query, String prefix, TIntArrayList list, int charMatches) throws IOException { + String key = null; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return charMatches; + case OsmandOdb.IndexedStringTable.KEY_FIELD_NUMBER : + key = codedIS.readString(); + if(prefix.length() > 0){ + key = prefix + key; + } + // check query is part of key (the best matching) + if(CollatorStringMatcher.cmatches(instance, key, query, StringMatcherMode.CHECK_ONLY_STARTS_WITH)){ + if(query.length() >= charMatches){ + if(query.length() > charMatches){ + charMatches = query.length(); + list.clear(); + } + } else { + key = null; + } + // check key is part of query + } else if (CollatorStringMatcher.cmatches(instance, query, key, StringMatcherMode.CHECK_ONLY_STARTS_WITH)) { + if (key.length() >= charMatches) { + if (key.length() > charMatches) { + charMatches = key.length(); + list.clear(); + } + } else { + key = null; + } + } else { + key = null; + } + break; + case OsmandOdb.IndexedStringTable.VAL_FIELD_NUMBER : + int val = readInt(); + if (key != null) { + list.add(val); + } + break; + case OsmandOdb.IndexedStringTable.SUBTABLES_FIELD_NUMBER : + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + if (key != null) { + charMatches = readIndexedStringTable(instance, query, key, list, charMatches); + } else { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + } + codedIS.popLimit(oldLim); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private static void testAddressSearchByName(BinaryMapIndexReader reader) throws IOException { + SearchRequest req = buildAddressByNameRequest(new ResultMatcher() { + @Override + public boolean publish(MapObject object) { + if(object instanceof Street) { + System.out.println(object + " " + ((Street) object).getCity()); + } else { + System.out.println(object); + } + return false; + } + @Override + public boolean isCancelled() { + return false; + } + }, "lux"); + reader.searchAddressDataByName(req); + } + + private static void testAddressSearch(BinaryMapIndexReader reader) throws IOException { + // test address index search + String reg = reader.getRegionNames().get(0); + final Map streetFreq = new HashMap(); + List cs = reader.getCities(reg, null, BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE); + for(City c : cs){ + int buildings = 0; + reader.preloadStreets(c, null); + for(Street s : c.getStreets()){ + updateFrequence(streetFreq, s.getName()); + reader.preloadBuildings(s, buildAddressRequest((ResultMatcher) null)); + buildings += s.getBuildings().size(); + } + println(c.getName() + " " + c.getLocation() + " " + c.getStreets().size() + " " + buildings + " " + c.getEnName()); + } +// int[] count = new int[1]; + List villages = reader.getCities(reg, buildAddressRequest((ResultMatcher) null), BinaryMapAddressReaderAdapter.VILLAGES_TYPE); + for(City v : villages) { + reader.preloadStreets(v, null); + for(Street s : v.getStreets()){ + updateFrequence(streetFreq, s.getName()); + } + } + System.out.println("Villages " + villages.size()); + + List sorted = new ArrayList(streetFreq.keySet()); + Collections.sort(sorted, new Comparator() { + @Override + public int compare(String o1, String o2) { + return - streetFreq.get(o1) + streetFreq.get(o2); + } + }); + System.out.println(streetFreq.size()); + for(String s : sorted) { + System.out.println(s + " " + streetFreq.get(s)); + if(streetFreq.get(s) < 10){ + break; + } + } + + } + + private static void testMapSearch(BinaryMapIndexReader reader) throws IOException { + println(reader.mapIndexes.get(0).encodingRules + ""); + println("SEARCH " + sleft + " " + sright + " " + stop + " " + sbottom); + + reader.searchMapIndex(buildSearchRequest(sleft, sright, stop, sbottom, szoom, null, new ResultMatcher() { + + @Override + public boolean publish(BinaryMapDataObject obj) { + + StringBuilder b = new StringBuilder(); + b.append(obj.area? "Area" : (obj.getPointsLength() > 1? "Way" : "Point")); + int[] types = obj.getTypes(); + b.append(" types ["); + for(int j = 0; j 0) { + b.append(", "); + } + TagValuePair pair = obj.getMapIndex().decodeType(types[j]); + if(pair == null) { + throw new NullPointerException("Type " + types[j] + "was not found"); + } + b.append(pair.toSimpleString()+"("+types[j]+")"); + } + b.append("]"); + if(obj.getAdditionalTypes() != null && obj.getAdditionalTypes().length > 0){ + b.append(" add_types ["); + for(int j = 0; j 0) { + b.append(", "); + } + TagValuePair pair = obj.getMapIndex().decodeType(obj.getAdditionalTypes()[j]); + if(pair == null) { + throw new NullPointerException("Type " + obj.getAdditionalTypes()[j] + "was not found"); + } + b.append(pair.toSimpleString()+"("+obj.getAdditionalTypes()[j]+")"); + + } + b.append("]"); + } + TIntObjectHashMap names = obj.getObjectNames(); + if(names != null && !names.isEmpty()) { + b.append(" Names ["); + int[] keys = names.keys(); + for(int j = 0; j 0) { + b.append(", "); + } + TagValuePair pair = obj.getMapIndex().decodeType(keys[j]); + if(pair == null) { + throw new NullPointerException("Type " + keys[j] + "was not found"); + } + b.append(pair.toSimpleString()+"("+keys[j]+")"); + b.append(" - ").append(names.get(keys[j])); + } + b.append("]"); + } + + b.append(" id ").append((obj.getId() >> 1)); + b.append(" lat/lon : "); + for(int i=0; i searchRouteIndexTree(SearchRequest req, List list) throws IOException { + req.numberOfVisitedObjects = 0; + req.numberOfAcceptedObjects = 0; + req.numberOfAcceptedSubtrees = 0; + req.numberOfReadSubtrees = 0; + if(routeAdapter != null){ + routeAdapter.initRouteTypesIfNeeded(req, list); + return routeAdapter.searchRouteRegionTree(req, list, new ArrayList()); + } + return Collections.emptyList(); + } + + public void loadRouteIndexData(List toLoad, ResultMatcher matcher) throws IOException { + if(routeAdapter != null){ + routeAdapter.loadRouteRegionData(toLoad, matcher); + } + } + + public List searchBorderPoints(SearchRequest req, RouteRegion r) throws IOException { + if(routeAdapter != null){ + routeAdapter.searchBorderPoints(req, r); + } + return Collections.emptyList(); + } + + public List loadRouteIndexData(RouteSubregion rs) throws IOException { + if(routeAdapter != null){ + return routeAdapter.loadRouteRegionData(rs); + } + return Collections.emptyList(); + } + + public void initRouteRegion(RouteRegion routeReg) throws IOException { + if(routeAdapter != null){ + routeAdapter.initRouteRegion(routeReg); + } + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java new file mode 100644 index 0000000000..e9b5a99db6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapPoiReaderAdapter.java @@ -0,0 +1,718 @@ +package net.osmand.binary; + + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntLongHashMap; +import gnu.trove.set.hash.TLongHashSet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import net.osmand.Collator; +import net.osmand.CollatorStringMatcher; +import net.osmand.CollatorStringMatcher.StringMatcherMode; +import net.osmand.PlatformUtil; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; +import net.sf.junidecode.Junidecode; + +import org.apache.commons.logging.Log; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.WireFormat; + +public class BinaryMapPoiReaderAdapter { + private static final Log LOG = PlatformUtil.getLog(BinaryMapPoiReaderAdapter.class); + + public static final int SHIFT_BITS_CATEGORY = 7; + private static final int CATEGORY_MASK = (1 << SHIFT_BITS_CATEGORY) - 1 ; + private static final int ZOOM_TO_SKIP_FILTER = 3; + private static final int BUCKET_SEARCH_BY_NAME = 5; + + public static class PoiRegion extends BinaryIndexPart { + + List categories = new ArrayList(); + List categoriesType = new ArrayList(); + List > subcategories = new ArrayList >(); + + double leftLongitude; + double rightLongitude; + double topLatitude; + double bottomLatitude; + + public double getLeftLongitude() { + return leftLongitude; + } + + public double getRightLongitude() { + return rightLongitude; + } + + public double getTopLatitude() { + return topLatitude; + } + + public double getBottomLatitude() { + return bottomLatitude; + } + } + + private CodedInputStream codedIS; + private final BinaryMapIndexReader map; + + protected BinaryMapPoiReaderAdapter(BinaryMapIndexReader map){ + this.codedIS = map.codedIS; + this.map = map; + } + + private void skipUnknownField(int t) throws IOException { + map.skipUnknownField(t); + } + + private int readInt() throws IOException { + return map.readInt(); + } + + private void readPoiBoundariesIndex(PoiRegion region) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndTileBox.LEFT_FIELD_NUMBER: + region.leftLongitude = MapUtils.get31LongitudeX(codedIS.readUInt32()); + break; + case OsmandOdb.OsmAndTileBox.RIGHT_FIELD_NUMBER: + region.rightLongitude = MapUtils.get31LongitudeX(codedIS.readUInt32()); + break; + case OsmandOdb.OsmAndTileBox.TOP_FIELD_NUMBER: + region.topLatitude = MapUtils.get31LatitudeY(codedIS.readUInt32()); + break; + case OsmandOdb.OsmAndTileBox.BOTTOM_FIELD_NUMBER: + region.bottomLatitude = MapUtils.get31LatitudeY(codedIS.readUInt32()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + + protected void readPoiIndex(PoiRegion region, boolean readCategories) throws IOException { + int length; + int oldLimit; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiIndex.NAME_FIELD_NUMBER : + region.name = codedIS.readString(); + break; + case OsmandOdb.OsmAndPoiIndex.BOUNDARIES_FIELD_NUMBER: + length = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(length); + readPoiBoundariesIndex(region); + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.OsmAndPoiIndex.CATEGORIESTABLE_FIELD_NUMBER : + if(!readCategories){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + } + length = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(length); + readCategory(region); + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER : + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + default: + skipUnknownField(t); + break; + } + } + } + + private void readCategory(PoiRegion region) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndCategoryTable.CATEGORY_FIELD_NUMBER : + String cat = codedIS.readString().intern(); + region.categories.add(cat); + region.categoriesType.add(AmenityType.fromString(cat)); + region.subcategories.add(new ArrayList()); + break; + case OsmandOdb.OsmAndCategoryTable.SUBCATEGORIES_FIELD_NUMBER : + region.subcategories.get(region.subcategories.size() - 1).add(codedIS.readString().intern()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + public void initCategories(PoiRegion region) throws IOException { + if(region.categories.isEmpty()) { + codedIS.seek(region.filePointer); + int oldLimit = codedIS.pushLimit(region.length); + readPoiIndex(region, true); + codedIS.popLimit(oldLimit); + } + } + + protected void searchPoiByName( PoiRegion region, SearchRequest req) throws IOException { + TIntLongHashMap offsets = new TIntLongHashMap(); + CollatorStringMatcher matcher = new CollatorStringMatcher(req.nameQuery, + StringMatcherMode.CHECK_STARTS_FROM_SPACE); + long time = System.currentTimeMillis(); + int indexOffset = codedIS.getTotalBytesRead(); + while(true){ + if(req.isCancelled()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiIndex.NAMEINDEX_FIELD_NUMBER : + int length = readInt(); + int oldLimit = codedIS.pushLimit(length); + // here offsets are sorted by distance + offsets = readPoiNameIndex(matcher.getCollator(), req.nameQuery, req); + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER : + // also offsets can be randomly skipped by limit + Integer[] offKeys = new Integer[offsets.size()]; + if (offsets.size() > 0) { + int[] keys = offsets.keys(); + for (int i = 0; i < keys.length; i++) { + offKeys[i] = keys[i]; + } + final TIntLongHashMap foffsets = offsets; + Arrays.sort(offKeys, new Comparator() { + @Override + public int compare(Integer object1, Integer object2) { + return Double.compare(foffsets.get(object1), foffsets.get(object2)); + } + }); + int p = BUCKET_SEARCH_BY_NAME * 3 ; + if (p < offKeys.length) { + for (int i = p + BUCKET_SEARCH_BY_NAME;; i += BUCKET_SEARCH_BY_NAME) { + if (i > offKeys.length) { + Arrays.sort(offKeys, p, offKeys.length); + break; + } else { + Arrays.sort(offKeys, p, i); + } + p = i; + } + } + } + + + LOG.info("Searched poi structure in "+(System.currentTimeMillis() - time) + + "ms. Found " + offKeys.length +" subtress"); + for (int j = 0; j < offKeys.length; j++) { + codedIS.seek(offKeys[j] + indexOffset); + int len = readInt(); + int oldLim = codedIS.pushLimit(len); + readPoiData(matcher, req, region); + codedIS.popLimit(oldLim); + if(req.isCancelled() || req.limitExceeded()){ + return; + } + } + LOG.info("Whole poi by name search is done in "+(System.currentTimeMillis() - time) + + "ms. Found " + req.getSearchResults().size()); + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + default: + skipUnknownField(t); + break; + } + } + } + + private TIntLongHashMap readPoiNameIndex(Collator instance, String query, SearchRequest req) throws IOException { + TIntLongHashMap offsets = new TIntLongHashMap(); + TIntArrayList dataOffsets = null; + int offset = 0; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return offsets; + case OsmandOdb.OsmAndPoiNameIndex.TABLE_FIELD_NUMBER : { + int length = readInt(); + int oldLimit = codedIS.pushLimit(length); + dataOffsets = new TIntArrayList(); + offset = codedIS.getTotalBytesRead(); + map.readIndexedStringTable(instance, query, "", dataOffsets, 0); + codedIS.popLimit(oldLimit); + break; } + case OsmandOdb.OsmAndPoiNameIndex.DATA_FIELD_NUMBER : { + if(dataOffsets != null){ + dataOffsets.sort(); // 1104125 + for (int i = 0; i < dataOffsets.size(); i++) { + codedIS.seek(dataOffsets.get(i) + offset); + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + readPoiNameIndexData(offsets, req); + codedIS.popLimit(oldLim); + if (req.isCancelled()) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return offsets; + } + } + } + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return offsets; } + default: + skipUnknownField(t); + break; + } + } + + } + + private void readPoiNameIndexData(TIntLongHashMap offsets, SearchRequest req) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmAndPoiNameIndexData.ATOMS_FIELD_NUMBER : + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + readPoiNameIndexDataAtom(offsets, req); + codedIS.popLimit(oldLim); + break; + default: + skipUnknownField(t); + break; + } + } + + } + + private void readPoiNameIndexDataAtom(TIntLongHashMap offsets, SearchRequest req) throws IOException { + int x = 0; + int y = 0; + int zoom = 15; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiNameIndexDataAtom.X_FIELD_NUMBER : + x = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiNameIndexDataAtom.Y_FIELD_NUMBER : + y = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiNameIndexDataAtom.ZOOM_FIELD_NUMBER : + zoom = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiNameIndexDataAtom.SHIFTTO_FIELD_NUMBER : + int x31 = (x << (31 - zoom)); + int y31 = (y << (31 - zoom)); + int shift = readInt(); + if (req.contains(x31, y31, x31, y31)) { + long d = Math.abs(req.x - x31) + Math.abs(req.y - y31); + offsets.put(shift, d); + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + + protected void searchPoiIndex(int left31, int right31, int top31, int bottom31, + SearchRequest req, PoiRegion region) throws IOException { + int indexOffset = codedIS.getTotalBytesRead(); + long time = System.currentTimeMillis(); + TLongHashSet skipTiles = null; + int zoomToSkip = 31; + if(req.zoom != -1){ + skipTiles = new TLongHashSet(); + zoomToSkip = req.zoom + ZOOM_TO_SKIP_FILTER; + } + int length ; + int oldLimit ; + TIntLongHashMap offsetsMap = new TIntLongHashMap(); + while(true){ + if(req.isCancelled()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiIndex.BOXES_FIELD_NUMBER : + length = readInt(); + oldLimit = codedIS.pushLimit(length); + readBoxField(left31, right31, top31, bottom31, 0, 0, 0, offsetsMap, skipTiles, req, region); + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.OsmAndPoiIndex.POIDATA_FIELD_NUMBER : + int[] offsets = offsetsMap.keys(); + // also offsets can be randomly skipped by limit + Arrays.sort(offsets); + if(skipTiles != null){ + skipTiles.clear(); + } + LOG.info("Searched poi structure in "+(System.currentTimeMillis() - time) + + "ms. Found " + offsets.length +" subtress"); + for (int j = 0; j < offsets.length; j++) { + codedIS.seek(offsets[j] + indexOffset); + int len = readInt(); + int oldLim = codedIS.pushLimit(len); + readPoiData(left31, right31, top31, bottom31, req, region, skipTiles, zoomToSkip); + codedIS.popLimit(oldLim); + if(req.isCancelled()){ + return; + } + } + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + default: + skipUnknownField(t); + break; + } + } + } + + private void readPoiData(CollatorStringMatcher matcher, SearchRequest req, PoiRegion region) throws IOException { + int x = 0; + int y = 0; + int zoom = 0; + while(true){ + if(req.isCancelled() || req.limitExceeded()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiBoxData.X_FIELD_NUMBER : + x = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.ZOOM_FIELD_NUMBER : + zoom = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.Y_FIELD_NUMBER : + y = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.POIDATA_FIELD_NUMBER: + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + Amenity am = readPoiPoint(0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, x, y, zoom, req, region, false); + codedIS.popLimit(oldLim); + if (am != null) { + if(matcher.matches(am.getName(false)) || matcher.matches(am.getName(true))) { + req.publish(am); + } + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + private void readPoiData(int left31, int right31, int top31, int bottom31, + SearchRequest req, PoiRegion region, TLongHashSet toSkip, int zSkip) throws IOException { + int x = 0; + int y = 0; + int zoom = 0; + while(true){ + if(req.isCancelled()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndPoiBoxData.X_FIELD_NUMBER : + x = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.ZOOM_FIELD_NUMBER : + zoom = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.Y_FIELD_NUMBER : + y = codedIS.readUInt32(); + break; + case OsmandOdb.OsmAndPoiBoxData.POIDATA_FIELD_NUMBER: + int len = codedIS.readRawVarint32(); + int oldLim = codedIS.pushLimit(len); + Amenity am = readPoiPoint(left31, right31, top31, bottom31, x, y, zoom, req, region, true); + codedIS.popLimit(oldLim); + if (am != null) { + if (toSkip != null) { + int xp = (int) MapUtils.getTileNumberX(zSkip, am.getLocation().getLongitude()); + int yp = (int) MapUtils.getTileNumberY(zSkip, am.getLocation().getLatitude()); + long val = (((long) xp) << zSkip) | yp; + if (!toSkip.contains(val)) { + boolean publish = req.publish(am); + if(publish) { + toSkip.add(val); + } + } + if(zSkip <= zoom){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return; + } + } else { + req.publish(am); + } + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + private Amenity readPoiPoint(int left31, int right31, int top31, int bottom31, + int px, int py, int zoom, SearchRequest req, PoiRegion region, boolean checkBounds) throws IOException { + Amenity am = null; + int x = 0; + int y = 0; + AmenityType amenityType = null; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + if(amenityType == null && (tag > OsmandOdb.OsmAndPoiBoxDataAtom.CATEGORIES_FIELD_NUMBER || tag == 0)) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + switch (tag) { + case 0: + if(Algorithms.isEmpty(am.getEnName())){ + am.setEnName(Junidecode.unidecode(am.getName())); + } + req.numberOfAcceptedObjects++; + return am; + case OsmandOdb.OsmAndPoiBoxDataAtom.DX_FIELD_NUMBER : + x = (codedIS.readSInt32() + (px << (24 - zoom))) << 7; + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.DY_FIELD_NUMBER : + y = (codedIS.readSInt32() + (py << (24 - zoom))) << 7; + req.numberOfVisitedObjects++; + if (checkBounds) { + if (left31 > x || right31 < x || top31 > y || bottom31 < y) { + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + } + am = new Amenity(); + am.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x)); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.CATEGORIES_FIELD_NUMBER : + int cat = codedIS.readUInt32(); + int subcatId = cat >> SHIFT_BITS_CATEGORY; + int catId = cat & CATEGORY_MASK; + AmenityType type = AmenityType.OTHER; + String subtype = ""; + if (catId < region.categoriesType.size()) { + type = region.categoriesType.get(catId); + List subcats = region.subcategories.get(catId); + if (subcatId < subcats.size()) { + subtype = subcats.get(subcatId); + } + } + if (req.poiTypeFilter == null || req.poiTypeFilter.accept(type, subtype)) { + if (amenityType == null) { + amenityType = type; + am.setSubType(subtype); + am.setType(amenityType); + } else { + am.setSubType(am.getSubType() + ";" + subtype); + } + } + + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.ID_FIELD_NUMBER : + am.setId(codedIS.readUInt64()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.NAME_FIELD_NUMBER : + am.setName(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.NAMEEN_FIELD_NUMBER : + am.setEnName(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.OPENINGHOURS_FIELD_NUMBER : + am.setOpeningHours(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.SITE_FIELD_NUMBER : + am.setSite(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.PHONE_FIELD_NUMBER: + am.setPhone(codedIS.readString()); + break; + case OsmandOdb.OsmAndPoiBoxDataAtom.NOTE_FIELD_NUMBER: + am.setDescription(codedIS.readString()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private boolean checkCategories(SearchRequest req, PoiRegion region) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return false; + case OsmandOdb.OsmAndPoiCategories.CATEGORIES_FIELD_NUMBER: + AmenityType type = AmenityType.OTHER; + String subcat = ""; + int cat = codedIS.readUInt32(); + int subcatId = cat >> SHIFT_BITS_CATEGORY; + int catId = cat & CATEGORY_MASK; + if(catId < region.categoriesType.size()){ + type = region.categoriesType.get(catId); + List subcats = region.subcategories.get(catId); + if(subcatId < subcats.size()){ + subcat = subcats.get(subcatId); + } + } else { + type = AmenityType.OTHER; + } + if(req.poiTypeFilter.accept(type, subcat)){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return true; + } + + break; + default: + skipUnknownField(t); + break; + } + } + } + + private boolean readBoxField(int left31, int right31, int top31, int bottom31, + int px, int py, int pzoom, TIntLongHashMap offsetsMap, TLongHashSet skipTiles, SearchRequest req, PoiRegion region) throws IOException { + req.numberOfReadSubtrees++; + int zoomToSkip = req.zoom + ZOOM_TO_SKIP_FILTER; + boolean checkBox = true; + boolean existsCategories = false; + int zoom = pzoom; + int dy = py; + int dx = px; + while(true){ + if(req.isCancelled()){ + return false; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return existsCategories; + case OsmandOdb.OsmAndPoiBox.ZOOM_FIELD_NUMBER : + zoom = codedIS.readUInt32() + pzoom; + break; + case OsmandOdb.OsmAndPoiBox.LEFT_FIELD_NUMBER : + dx = codedIS.readSInt32(); + break; + case OsmandOdb.OsmAndPoiBox.TOP_FIELD_NUMBER: + dy = codedIS.readSInt32(); + break; + case OsmandOdb.OsmAndPoiBox.CATEGORIES_FIELD_NUMBER: + if(req.poiTypeFilter == null){ + skipUnknownField(t); + } else { + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + boolean check = checkCategories(req, region); + codedIS.popLimit(oldLimit); + if(!check){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return false; + } + existsCategories = true; + } + break; + + case OsmandOdb.OsmAndPoiBox.SUBBOXES_FIELD_NUMBER: { + int x = dx + (px << (zoom - pzoom)); + int y = dy + (py << (zoom - pzoom)); + if(checkBox){ + int xL = x << (31 - zoom); + int xR = ((x + 1) << (31 - zoom)) - 1; + int yT = y << (31 - zoom); + int yB = ((y + 1) << (31 - zoom)) - 1; + // check intersection + if(left31 > xR || xL > right31 || bottom31 < yT || yB < top31){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return false; + } + req.numberOfAcceptedSubtrees++; + checkBox = false; + } + + int length = readInt(); + int oldLimit = codedIS.pushLimit(length); + boolean exists = readBoxField(left31, right31, top31, bottom31, x, y, zoom, offsetsMap, skipTiles, req, region); + codedIS.popLimit(oldLimit); + + if (skipTiles != null && zoom >= zoomToSkip && exists) { + long val = ((((long) x) >> (zoom - zoomToSkip)) << zoomToSkip) | (((long) y) >> (zoom - zoomToSkip)); + if(skipTiles.contains(val)){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return true; + } + } + } break; + case OsmandOdb.OsmAndPoiBox.SHIFTTODATA_FIELD_NUMBER: { + int x = dx + (px << (zoom - pzoom)); + int y = dy + (py << (zoom - pzoom)); + long l = ((((x << zoom) | y) << 5) | zoom); + offsetsMap.put(readInt(), l); + if(skipTiles != null && zoom >= zoomToSkip){ + long val = ((((long) x) >> (zoom - zoomToSkip)) << zoomToSkip) | (((long) y) >> (zoom - zoomToSkip)); + skipTiles.add(val); + } + } break; + default: + skipUnknownField(t); + break; + } + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java new file mode 100644 index 0000000000..54edf12173 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -0,0 +1,927 @@ +package net.osmand.binary; + +import gnu.trove.iterator.TLongObjectIterator; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.list.array.TLongArrayList; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.map.hash.TLongObjectHashMap; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.osmand.PlatformUtil; +import net.osmand.ResultMatcher; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.OsmandOdb.IdTable; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.Builder; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox; +import net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule; +import net.osmand.binary.OsmandOdb.RestrictionData; +import net.osmand.binary.OsmandOdb.RouteData; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.WireFormat; + +public class BinaryMapRouteReaderAdapter { + protected static final Log LOG = PlatformUtil.getLog(BinaryMapRouteReaderAdapter.class); + private static final int SHIFT_COORDINATES = 4; + + public static class RouteTypeRule { + private final static int ACCESS = 1; + private final static int ONEWAY = 2; + private final static int HIGHWAY_TYPE = 3; + private final static int MAXSPEED = 4; + private final static int ROUNDABOUT = 5; + public final static int TRAFFIC_SIGNALS = 6; + public final static int RAILWAY_CROSSING = 7; + private final static int LANES = 8; + private final String t; + private final String v; + private int intValue; + private float floatValue; + private int type; + + public RouteTypeRule(String t, String v) { + this.t = t.intern(); + if("true".equals(v)) { + v = "yes"; + } + if("false".equals(v)) { + v = "no"; + } + this.v = v == null? null : v.intern(); + analyze(); + } + + public String getTag() { + return t; + } + + public String getValue(){ + return v; + } + + public boolean roundabout(){ + return type == ROUNDABOUT; + } + + public int getType() { + return type; + } + + public int onewayDirection(){ + if(type == ONEWAY){ + return intValue; + } + return 0; + } + + public float maxSpeed(){ + if(type == MAXSPEED){ + return floatValue; + } + return -1; + } + + public int lanes(){ + if(type == LANES){ + return intValue; + } + return -1; + } + + public String highwayRoad(){ + if(type == HIGHWAY_TYPE){ + return v; + } + return null; + } + + private void analyze() { + if(t.equalsIgnoreCase("oneway")){ + type = ONEWAY; + if("-1".equals(v) || "reverse".equals(v)) { + intValue = -1; + } else if("1".equals(v) || "yes".equals(v)) { + intValue = 1; + } else { + intValue = 0; + } + } else if(t.equalsIgnoreCase("highway") && "traffic_signals".equals(v)){ + type = TRAFFIC_SIGNALS; + } else if(t.equalsIgnoreCase("railway") && ("crossing".equals(v) || "level_crossing".equals(v))){ + type = RAILWAY_CROSSING; + } else if(t.equalsIgnoreCase("roundabout") && v != null){ + type = ROUNDABOUT; + } else if(t.equalsIgnoreCase("junction") && "roundabout".equalsIgnoreCase(v)){ + type = ROUNDABOUT; + } else if(t.equalsIgnoreCase("highway") && v != null){ + type = HIGHWAY_TYPE; + } else if(t.startsWith("access") && v != null){ + type = ACCESS; + } else if(t.equalsIgnoreCase("maxspeed") && v != null){ + type = MAXSPEED; + floatValue = -1; + if(v.equals("none")) { + floatValue = RouteDataObject.NONE_MAX_SPEED; + } else { + int i = 0; + while (i < v.length() && Character.isDigit(v.charAt(i))) { + i++; + } + if (i > 0) { + floatValue = Integer.parseInt(v.substring(0, i)); + floatValue /= 3.6; // km/h -> m/s + if (v.contains("mph")) { + floatValue *= 1.6; + } + } + } + } else if (t.equalsIgnoreCase("lanes") && v != null) { + intValue = -1; + int i = 0; + type = LANES; + while (i < v.length() && Character.isDigit(v.charAt(i))) { + i++; + } + if (i > 0) { + intValue = Integer.parseInt(v.substring(0, i)); + } + } + + } + } + + public static class RouteRegion extends BinaryIndexPart { + public int regionsRead; + public int borderBoxPointer = 0; + public int baseBorderBoxPointer = 0; + public int borderBoxLength = 0; + public int baseBorderBoxLength = 0; + + List subregions = new ArrayList(); + List basesubregions = new ArrayList(); + List routeEncodingRules = new ArrayList(); + + int nameTypeRule = -1; + int refTypeRule = -1; + int destinationTypeRule = -1; + + public RouteTypeRule quickGetEncodingRule(int id) { + return routeEncodingRules.get(id); + } + + private void initRouteEncodingRule(int id, String tags, String val) { + while(routeEncodingRules.size() <= id) { + routeEncodingRules.add(null); + } + routeEncodingRules.set(id, new RouteTypeRule(tags, val)); + if(tags.equals("name")) { + nameTypeRule = id; + } else if(tags.equals("ref")) { + refTypeRule = id; + } else if(tags.equals("destination")) { + destinationTypeRule = id; + } + } + + public List getSubregions(){ + return subregions; + } + + public List getBaseSubregions(){ + return basesubregions; + } + + public double getLeftLongitude() { + double l = 180; + for(RouteSubregion s : subregions) { + l = Math.min(l, MapUtils.get31LongitudeX(s.left)); + } + return l; + } + + public double getRightLongitude() { + double l = -180; + for(RouteSubregion s : subregions) { + l = Math.max(l, MapUtils.get31LongitudeX(s.right)); + } + return l; + } + + public double getBottomLatitude() { + double l = 90; + for(RouteSubregion s : subregions) { + l = Math.min(l, MapUtils.get31LatitudeY(s.bottom)); + } + return l; + } + + public double getTopLatitude() { + double l = -90; + for(RouteSubregion s : subregions) { + l = Math.max(l, MapUtils.get31LatitudeY(s.top)); + } + return l; + } + } + + // Used in C++ + public static class RouteSubregion { + private final static int INT_SIZE = 4; + public final RouteRegion routeReg; + public RouteSubregion(RouteSubregion copy) { + this.routeReg = copy.routeReg; + this.left = copy.left; + this.right = copy.right; + this.top = copy.top; + this.bottom = copy.bottom; + this.filePointer = copy.filePointer; + this.length = copy.length; + + } + public RouteSubregion(RouteRegion routeReg) { + this.routeReg = routeReg; + } + public int length; + public int filePointer; + public int left; + public int right; + public int top; + public int bottom; + public int shiftToData; + public List subregions = null; + public List dataObjects = null; + + public int getEstimatedSize(){ + int shallow = 7 * INT_SIZE + 4*3; + if (subregions != null) { + shallow += 8; + for (RouteSubregion s : subregions) { + shallow += s.getEstimatedSize(); + } + } + return shallow; + } + + public int countSubregions(){ + int cnt = 1; + if (subregions != null) { + for (RouteSubregion s : subregions) { + cnt += s.countSubregions(); + } + } + return cnt; + } + } + + private CodedInputStream codedIS; + private final BinaryMapIndexReader map; + + protected BinaryMapRouteReaderAdapter(BinaryMapIndexReader map){ + this.codedIS = map.codedIS; + this.map = map; + } + + private void skipUnknownField(int t) throws IOException { + map.skipUnknownField(t); + } + + private int readInt() throws IOException { + return map.readInt(); + } + + + protected void readRouteIndex(RouteRegion region) throws IOException { + int routeEncodingRule =1; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndRoutingIndex.NAME_FIELD_NUMBER : + region.name = codedIS.readString(); + break; + case OsmandOdb.OsmAndRoutingIndex.RULES_FIELD_NUMBER: { + int len = codedIS.readInt32(); + int oldLimit = codedIS.pushLimit(len); + readRouteEncodingRule(region, routeEncodingRule++); + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + codedIS.popLimit(oldLimit); + } break; + case OsmandOdb.OsmAndRoutingIndex.ROOTBOXES_FIELD_NUMBER : + case OsmandOdb.OsmAndRoutingIndex.BASEMAPBOXES_FIELD_NUMBER :{ + RouteSubregion subregion = new RouteSubregion(region); + subregion.length = readInt(); + subregion.filePointer = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(subregion.length); + readRouteTree(subregion, null, 0, true); + if(tag == OsmandOdb.OsmAndRoutingIndex.ROOTBOXES_FIELD_NUMBER) { + region.subregions.add(subregion); + } else { + region.basesubregions.add(subregion); + } + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + codedIS.popLimit(oldLimit); + break; + } + case OsmandOdb.OsmAndRoutingIndex.BASEBORDERBOX_FIELD_NUMBER: + case OsmandOdb.OsmAndRoutingIndex.BORDERBOX_FIELD_NUMBER: { + int length = readInt(); + int filePointer = codedIS.getTotalBytesRead(); + if(tag == OsmandOdb.OsmAndRoutingIndex.BORDERBOX_FIELD_NUMBER) { + region.borderBoxLength = length; + region.borderBoxPointer = filePointer; + } else { + region.baseBorderBoxLength = length; + region.baseBorderBoxPointer = filePointer; + } + codedIS.skipRawBytes(length); + break; + } + case OsmandOdb.OsmAndRoutingIndex.BLOCKS_FIELD_NUMBER : { + // Finish reading file! + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + break; + } + + + default: + skipUnknownField(t); + break; + } + } + } + + private RouteDataObject readRouteDataObject(RouteRegion reg, int pleftx, int ptopy) throws IOException { + RouteDataObject o = new RouteDataObject(reg); + TIntArrayList pointsX = new TIntArrayList(); + TIntArrayList pointsY = new TIntArrayList(); + TIntArrayList types = new TIntArrayList(); + List globalpointTypes = new ArrayList(); + while (true) { + int ts = codedIS.readTag(); + int tags = WireFormat.getTagFieldNumber(ts); + switch (tags) { + case 0: + o.pointsX = pointsX.toArray(); + o.pointsY = pointsY.toArray(); + o.types = types.toArray(); + if(globalpointTypes.size() > 0){ + o.pointTypes = new int[globalpointTypes.size()][]; + for(int k=0; k 0) { + types.add(codedIS.readRawVarint32()); + } + codedIS.popLimit(oldLimit); + break; + case RouteData.STRINGNAMES_FIELD_NUMBER: + o.names = new TIntObjectHashMap(); + int sizeL = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(sizeL); + while (codedIS.getBytesUntilLimit() > 0) { + int stag = codedIS.readRawVarint32(); + int pId = codedIS.readRawVarint32(); + o.names.put(stag, ((char)pId)+""); + } + codedIS.popLimit(old); + break; + case RouteData.POINTS_FIELD_NUMBER: + len = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(len); + int px = pleftx >> SHIFT_COORDINATES; + int py = ptopy >> SHIFT_COORDINATES; + while(codedIS.getBytesUntilLimit() > 0){ + int x = (codedIS.readSInt32() ) + px; + int y = (codedIS.readSInt32() ) + py; + pointsX.add(x << SHIFT_COORDINATES); + pointsY.add(y << SHIFT_COORDINATES); + px = x; + py = y; + } + codedIS.popLimit(oldLimit); + break; + case RouteData.POINTTYPES_FIELD_NUMBER: + len = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(len); + while (codedIS.getBytesUntilLimit() > 0) { + int pointInd = codedIS.readRawVarint32(); + TIntArrayList pointTypes = new TIntArrayList(); + int lens = codedIS.readRawVarint32(); + int oldLimits = codedIS.pushLimit(lens); + while (codedIS.getBytesUntilLimit() > 0) { + pointTypes.add(codedIS.readRawVarint32()); + } + codedIS.popLimit(oldLimits); + while (pointInd >= globalpointTypes.size()) { + globalpointTypes.add(null); + } + globalpointTypes.set(pointInd, pointTypes); + + } + codedIS.popLimit(oldLimit); + break; + case RouteData.ROUTEID_FIELD_NUMBER: + o.id = codedIS.readInt32(); + break; + default: + skipUnknownField(ts); + break; + } + } + } + private void readRouteTreeData(RouteSubregion routeTree, TLongArrayList idTables, + TLongObjectHashMap restrictions) throws IOException { + routeTree.dataObjects = new ArrayList(); + idTables.clear(); + restrictions.clear(); + List stringTable = null; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + TLongObjectIterator it = restrictions.iterator(); + while (it.hasNext()) { + it.advance(); + int from = (int) it.key(); + RouteDataObject fromr = routeTree.dataObjects.get(from); + fromr.restrictions = new long[it.value().size()]; + for (int k = 0; k < fromr.restrictions.length; k++) { + int to = (int) (it.value().get(k) >> RouteDataObject.RESTRICTION_SHIFT); + long valto = (idTables.get(to) << RouteDataObject.RESTRICTION_SHIFT) | ((long) it.value().get(k) & RouteDataObject.RESTRICTION_MASK); + fromr.restrictions[k] = valto; + } + } + for (RouteDataObject o : routeTree.dataObjects) { + if (o != null) { + if (o.id < idTables.size()) { + o.id = idTables.get((int) o.id); + } + if (o.names != null && stringTable != null) { + int[] keys = o.names.keys(); + for (int j = 0; j < keys.length; j++) { + o.names.put(keys[j], stringTable.get(o.names.get(keys[j]).charAt(0))); + } + } + } + } + return; + case RouteDataBlock.DATAOBJECTS_FIELD_NUMBER : + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + RouteDataObject obj = readRouteDataObject(routeTree.routeReg, routeTree.left, routeTree.top); + while(obj.id >= routeTree.dataObjects.size()) { + routeTree.dataObjects.add(null); + } + routeTree.dataObjects.set((int) obj.id,obj); + codedIS.popLimit(oldLimit); + break; + case RouteDataBlock.IDTABLE_FIELD_NUMBER : + long routeId = 0; + length = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(length); + idLoop : while(true){ + int ts = codedIS.readTag(); + int tags = WireFormat.getTagFieldNumber(ts); + switch (tags) { + case 0: + break idLoop; + case IdTable.ROUTEID_FIELD_NUMBER : + routeId += codedIS.readSInt64(); + idTables.add(routeId); + break; + default: + skipUnknownField(ts); + break; + } + } + codedIS.popLimit(oldLimit); + break; + case RouteDataBlock.RESTRICTIONS_FIELD_NUMBER : + length = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(length); + long from = 0; + long to = 0; + long type = 0; + idLoop : while(true){ + int ts = codedIS.readTag(); + int tags = WireFormat.getTagFieldNumber(ts); + switch (tags) { + case 0: + break idLoop; + case RestrictionData.FROM_FIELD_NUMBER : + from = codedIS.readInt32(); + break; + case RestrictionData.TO_FIELD_NUMBER : + to = codedIS.readInt32(); + break; + case RestrictionData.TYPE_FIELD_NUMBER : + type = codedIS.readInt32(); + break; + default: + skipUnknownField(ts); + break; + } + } + if(!restrictions.containsKey(from)) { + restrictions.put(from, new TLongArrayList()); + } + restrictions.get(from).add((to << RouteDataObject.RESTRICTION_SHIFT) + type); + codedIS.popLimit(oldLimit); + break; + case RouteDataBlock.STRINGTABLE_FIELD_NUMBER : + length = codedIS.readRawVarint32(); + oldLimit = codedIS.pushLimit(length); + stringTable = map.readStringTable(); +// codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + codedIS.popLimit(oldLimit); + break; + default: + skipUnknownField(t); + break; + } + } + } + + + + private void readRouteEncodingRule(RouteRegion index, int id) throws IOException { + String tags = null; + String val = null; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + index.initRouteEncodingRule(id, tags, val); + return; + case RouteEncodingRule.VALUE_FIELD_NUMBER : + val = codedIS.readString().intern(); + break; + case RouteEncodingRule.TAG_FIELD_NUMBER : + tags = codedIS.readString().intern(); + break; + case RouteEncodingRule.ID_FIELD_NUMBER : + id = codedIS.readUInt32(); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private RouteSubregion readRouteTree(RouteSubregion thisTree, RouteSubregion parentTree, int depth, + boolean readCoordinates) throws IOException { + boolean readChildren = depth != 0; + if(readChildren) { + thisTree.subregions = new ArrayList(); + } + thisTree.routeReg.regionsRead++; + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return thisTree; + case RouteDataBox.LEFT_FIELD_NUMBER : + int i = codedIS.readSInt32(); + if (readCoordinates) { + thisTree.left = i + (parentTree != null ? parentTree.left : 0); + } + break; + case RouteDataBox.RIGHT_FIELD_NUMBER : + i = codedIS.readSInt32(); + if (readCoordinates) { + thisTree.right = i + (parentTree != null ? parentTree.right : 0); + } + break; + case RouteDataBox.TOP_FIELD_NUMBER : + i = codedIS.readSInt32(); + if (readCoordinates) { + thisTree.top = i + (parentTree != null ? parentTree.top : 0); + } + break; + case RouteDataBox.BOTTOM_FIELD_NUMBER : + i = codedIS.readSInt32(); + if (readCoordinates) { + thisTree.bottom = i + (parentTree != null ? parentTree.bottom : 0); + } + break; + case RouteDataBox.SHIFTTODATA_FIELD_NUMBER : + thisTree.shiftToData = readInt(); + if(!readChildren) { + // usually 0 + thisTree.subregions = new ArrayList(); + readChildren = true; + } + break; + case RouteDataBox.BOXES_FIELD_NUMBER : + if(readChildren){ + RouteSubregion subregion = new RouteSubregion(thisTree.routeReg); + subregion.length = readInt(); + subregion.filePointer = codedIS.getTotalBytesRead(); + int oldLimit = codedIS.pushLimit(subregion.length); + readRouteTree(subregion, thisTree, depth - 1, true); + thisTree.subregions.add(subregion); + codedIS.popLimit(oldLimit); + codedIS.seek(subregion.filePointer + subregion.length); + } else { + codedIS.seek(thisTree.filePointer + thisTree.length); + // skipUnknownField(t); + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + public void initRouteTypesIfNeeded(SearchRequest req, List list) throws IOException { + for (RouteSubregion rs : list) { + if (req.intersects(rs.left, rs.top, rs.right, rs.bottom)) { + initRouteRegion(rs.routeReg); + } + } + } + + public void initRouteRegion(RouteRegion routeReg) throws IOException, InvalidProtocolBufferException { + if (routeReg.routeEncodingRules.isEmpty()) { + codedIS.seek(routeReg.filePointer); + int oldLimit = codedIS.pushLimit(routeReg.length); + readRouteIndex(routeReg); + codedIS.popLimit(oldLimit); + } + } + + + public List loadRouteRegionData(RouteSubregion rs) throws IOException { + TLongArrayList idMap = new TLongArrayList(); + TLongObjectHashMap restrictionMap = new TLongObjectHashMap(); + if (rs.dataObjects == null) { + codedIS.seek(rs.filePointer + rs.shiftToData); + int limit = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(limit); + readRouteTreeData(rs, idMap, restrictionMap); + codedIS.popLimit(oldLimit); + } + List res = rs.dataObjects; + rs.dataObjects = null; + return res; + } + + public void loadRouteRegionData(List toLoad, ResultMatcher matcher) throws IOException { + Collections.sort(toLoad, new Comparator() { + @Override + public int compare(RouteSubregion o1, RouteSubregion o2) { + int p1 = o1.filePointer + o1.shiftToData; + int p2 = o2.filePointer + o2.shiftToData; + return p1 == p2 ? 0 : (p1 < p2 ? -1 : 1); + } + }); + TLongArrayList idMap = new TLongArrayList(); + TLongObjectHashMap restrictionMap = new TLongObjectHashMap(); + for (RouteSubregion rs : toLoad) { + if (rs.dataObjects == null) { + codedIS.seek(rs.filePointer + rs.shiftToData); + int limit = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(limit); + readRouteTreeData(rs, idMap, restrictionMap); + codedIS.popLimit(oldLimit); + } + for (RouteDataObject ro : rs.dataObjects) { + if (ro != null) { + matcher.publish(ro); + } + } + // free objects + rs.dataObjects = null; + } + } + + public List searchRouteRegionTree(SearchRequest req, List list, + List toLoad) throws IOException { + for (RouteSubregion rs : list) { + if (req.intersects(rs.left, rs.top, rs.right, rs.bottom)) { + if (rs.subregions == null) { + codedIS.seek(rs.filePointer); + int old = codedIS.pushLimit(rs.length); + readRouteTree(rs, null, req.contains(rs.left, rs.top, rs.right, rs.bottom) ? -1 : 1, false); + codedIS.popLimit(old); + } + searchRouteRegionTree(req, rs.subregions, toLoad); + + if (rs.shiftToData != 0) { + toLoad.add(rs); + } + } + } + return toLoad; + } + + public List searchBorderPoints(SearchRequest req, RouteRegion r) throws IOException { + if(r.borderBoxPointer != 0) { + codedIS.seek(r.borderBoxPointer); + int old = codedIS.pushLimit(r.borderBoxLength); + TIntArrayList blocksToRead = new TIntArrayList(); + readBorderLines(req, blocksToRead); + + blocksToRead.sort(); + for(int j = 0; j< blocksToRead.size() ; j++) { + codedIS.seek(blocksToRead.get(j)); + int len = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(len); + readBorderLinePoints(req, r); + codedIS.popLimit(oldLimit); + } + codedIS.popLimit(old); + + } + return req.getSearchResults(); + } + + + private void readBorderLinePoints(SearchRequest req, RouteRegion r) throws IOException { + int x = 0; + int y = 0; + long id = 0; + while (true) { + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case RouteBorderPointsBlock.X_FIELD_NUMBER: { + x = codedIS.readInt32(); + break; + } + case RouteBorderPointsBlock.Y_FIELD_NUMBER: { + y = codedIS.readInt32(); + break; + } + case RouteBorderPointsBlock.BASEID_FIELD_NUMBER: { + id = codedIS.readInt64(); + break; + } + case RouteBorderPointsBlock.POINTS_FIELD_NUMBER: + int len = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(len); + RouteDataBorderLinePoint p = readBorderLinePoint(new RouteDataBorderLinePoint(r), x, y, id); + codedIS.popLimit(oldLimit); + x = p.x; + y = p.y; + id = p.id; + req.publish(p); + break; + default: + skipUnknownField(t); + break; + } + } + + } + + private RouteDataBorderLinePoint readBorderLinePoint(RouteDataBorderLinePoint p, int x, int y, long id) throws IOException { + while (true) { + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return p; + case RouteBorderPoint.DX_FIELD_NUMBER: + p.x = x + codedIS.readInt32(); + break; + case RouteBorderPoint.DY_FIELD_NUMBER: + p.y = y + codedIS.readInt32(); + break; + case RouteBorderPoint.ROADID_FIELD_NUMBER: + p.id = id + codedIS.readSInt64(); + break; + case RouteBorderPoint.DIRECTION_FIELD_NUMBER: + p.direction = codedIS.readBool(); + break; + case RouteBorderPoint.TYPES_FIELD_NUMBER: + TIntArrayList types = new TIntArrayList(); + int len = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(len); + while(codedIS.getBytesUntilLimit() > 0) { + types.add(codedIS.readRawVarint32()); + } + codedIS.popLimit(oldLimit); + p.types = types.toArray(); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private void readBorderLines(SearchRequest req, TIntArrayList blocksToRead) throws IOException { + while (true) { + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case RouteBorderBox.BORDERLINES_FIELD_NUMBER: { + int fp = codedIS.getTotalBytesRead(); + int length = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(length); + + RouteBorderLine ln = readBorderLine(); + if(ln.hasTox() && req.intersects(ln.getX(), ln.getY(), ln.getTox(), ln.getY())) { + blocksToRead.add(ln.getShiftToPointsBlock() + fp); + // FIXME borders approach +// } else if(ln.hasToy() && req.intersects(ln.getX(), ln.getY(), ln.getX(), ln.getToy())) { +// blocksToRead.add(ln.getShiftToPointsBlock() + fp); + } + codedIS.popLimit(old); + break; + } + case RouteBorderBox.BLOCKS_FIELD_NUMBER: + return; + default: + skipUnknownField(t); + break; + } + } + + } + + private RouteBorderLine readBorderLine() throws IOException { + Builder bld = RouteBorderLine.newBuilder(); + while (true) { + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return bld.build(); + case RouteBorderLine.X_FIELD_NUMBER: + bld.setX(codedIS.readInt32()); + break; + case RouteBorderLine.Y_FIELD_NUMBER: + bld.setY(codedIS.readInt32()); + break; + case RouteBorderLine.TOX_FIELD_NUMBER: + bld.setTox(codedIS.readInt32()); + break; + case RouteBorderLine.TOY_FIELD_NUMBER: + bld.setToy(codedIS.readInt32()); + break; + case RouteBorderLine.SHIFTTOPOINTSBLOCK_FIELD_NUMBER: + bld.setShiftToPointsBlock(readInt()); + break; + default: + skipUnknownField(t); + break; + } + } + } + + public List loadInteresectedPoints(SearchRequest req, List list, + List toLoad) throws IOException { + for (RouteSubregion rs : list) { + if (req.intersects(rs.left, rs.top, rs.right, rs.bottom)) { + if (rs.subregions == null) { + codedIS.seek(rs.filePointer); + int old = codedIS.pushLimit(rs.length); + readRouteTree(rs, null, req.contains(rs.left, rs.top, rs.right, rs.bottom) ? -1 : 1, false); + codedIS.popLimit(old); + } + searchRouteRegionTree(req, rs.subregions, toLoad); + + if (rs.shiftToData != 0) { + toLoad.add(rs); + } + } + } + return toLoad; + } + +} diff --git a/OsmAnd-java/src/net/osmand/binary/BinaryMapTransportReaderAdapter.java b/OsmAnd-java/src/net/osmand/binary/BinaryMapTransportReaderAdapter.java new file mode 100644 index 0000000000..13adc6242c --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/BinaryMapTransportReaderAdapter.java @@ -0,0 +1,480 @@ +package net.osmand.binary; + +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntObjectHashMap; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.data.TransportStop; +import net.osmand.util.MapUtils; +import net.sf.junidecode.Junidecode; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.WireFormat; + +public class BinaryMapTransportReaderAdapter { + private CodedInputStream codedIS; + private final BinaryMapIndexReader map; + + protected BinaryMapTransportReaderAdapter(BinaryMapIndexReader map){ + this.codedIS = map.codedIS; + this.map = map; + } + + private void skipUnknownField(int t) throws IOException { + map.skipUnknownField(t); + } + + private int readInt() throws IOException { + return map.readInt(); + } + + public static class TransportIndex extends BinaryIndexPart { + + int left = 0; + int right = 0; + int top = 0; + int bottom = 0; + + int stopsFileOffset = 0; + int stopsFileLength = 0; + + public int getLeft() { + return left; + } + + public int getRight() { + return right; + } + + public int getTop() { + return top; + } + + public int getBottom() { + return bottom; + } + + IndexStringTable stringTable = null; + } + + protected static class IndexStringTable { + int fileOffset = 0; + int length = 0; + + // offset from start for each SIZE_OFFSET_ARRAY elements + // (SIZE_OFFSET_ARRAY + 1) offset = offsets[0] + skipOneString() + TIntArrayList offsets = new TIntArrayList(); + + } + + + protected void readTransportIndex(TransportIndex ind) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.OsmAndTransportIndex.ROUTES_FIELD_NUMBER : + skipUnknownField(t); + break; + case OsmandOdb.OsmAndTransportIndex.NAME_FIELD_NUMBER : + ind.setName(codedIS.readString()); + break; + case OsmandOdb.OsmAndTransportIndex.STOPS_FIELD_NUMBER : + ind.stopsFileLength = readInt(); + ind.stopsFileOffset = codedIS.getTotalBytesRead(); + int old = codedIS.pushLimit(ind.stopsFileLength); + readTransportBounds(ind); + codedIS.popLimit(old); + break; + case OsmandOdb.OsmAndTransportIndex.STRINGTABLE_FIELD_NUMBER : + IndexStringTable st = new IndexStringTable(); + st.length = codedIS.readRawVarint32(); + st.fileOffset = codedIS.getTotalBytesRead(); + // Do not cache for now save memory + // readStringTable(st, 0, 20, true); + ind.stringTable = st; + codedIS.seek(st.length + st.fileOffset); + break; + default: + skipUnknownField(t); + break; + } + } + } + + private void readTransportBounds(TransportIndex ind) throws IOException { + while(true){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + return; + case OsmandOdb.TransportStopsTree.LEFT_FIELD_NUMBER : + ind.left = codedIS.readSInt32(); + break; + case OsmandOdb.TransportStopsTree.RIGHT_FIELD_NUMBER : + ind.right = codedIS.readSInt32(); + break; + case OsmandOdb.TransportStopsTree.TOP_FIELD_NUMBER : + ind.top = codedIS.readSInt32(); + break; + case OsmandOdb.TransportStopsTree.BOTTOM_FIELD_NUMBER : + ind.bottom = codedIS.readSInt32(); + break; + default: + skipUnknownField(t); + break; + } + } + } + + protected void searchTransportTreeBounds(int pleft, int pright, int ptop, int pbottom, + SearchRequest req) throws IOException { + int init = 0; + int lastIndexResult = -1; + int cright = 0; + int cleft = 0; + int ctop = 0; + int cbottom = 0; + req.numberOfReadSubtrees++; + while(true){ + if(req.isCancelled()){ + return; + } + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + if(init == 0xf){ + // coordinates are init + init = 0; + if(cright < req.left || cleft > req.right || ctop > req.bottom || cbottom < req.top){ + return; + } else { + req.numberOfAcceptedSubtrees++; + } + } + switch (tag) { + case 0: + return; + case OsmandOdb.TransportStopsTree.BOTTOM_FIELD_NUMBER : + cbottom = codedIS.readSInt32() + pbottom; + init |= 1; + break; + case OsmandOdb.TransportStopsTree.LEFT_FIELD_NUMBER : + cleft = codedIS.readSInt32() + pleft; + init |= 2; + break; + case OsmandOdb.TransportStopsTree.RIGHT_FIELD_NUMBER : + cright = codedIS.readSInt32() + pright; + init |= 4; + break; + case OsmandOdb.TransportStopsTree.TOP_FIELD_NUMBER : + ctop = codedIS.readSInt32() + ptop; + init |= 8; + break; + case OsmandOdb.TransportStopsTree.LEAFS_FIELD_NUMBER : + int stopOffset = codedIS.getTotalBytesRead(); + int length = codedIS.readRawVarint32(); + int oldLimit = codedIS.pushLimit(length); + if(lastIndexResult == -1){ + lastIndexResult = req.getSearchResults().size(); + } + req.numberOfVisitedObjects++; + TransportStop transportStop = readTransportStop(stopOffset, cleft, cright, ctop, cbottom, req); + if(transportStop != null){ + req.publish(transportStop); + } + codedIS.popLimit(oldLimit); + break; + case OsmandOdb.TransportStopsTree.SUBTREES_FIELD_NUMBER : + // left, ... already initialized + length = readInt(); + int filePointer = codedIS.getTotalBytesRead(); + if (req.limit == -1 || req.limit >= req.getSearchResults().size()) { + oldLimit = codedIS.pushLimit(length); + searchTransportTreeBounds(cleft, cright, ctop, cbottom, req); + codedIS.popLimit(oldLimit); + } + codedIS.seek(filePointer + length); + + if(lastIndexResult >= 0){ + throw new IllegalStateException(); + } + break; + case OsmandOdb.TransportStopsTree.BASEID_FIELD_NUMBER : + long baseId = codedIS.readUInt64(); + if (lastIndexResult != -1) { + for (int i = lastIndexResult; i < req.getSearchResults().size(); i++) { + TransportStop rs = req.getSearchResults().get(i); + rs.setId(rs.getId() + baseId); + } + } + break; + default: + skipUnknownField(t); + break; + } + } + } + + private String regStr(TIntObjectHashMap stringTable) throws IOException{ + int i = codedIS.readUInt32(); + stringTable.putIfAbsent(i, ""); + return ((char) i)+""; + } + + public net.osmand.data.TransportRoute getTransportRoute(int filePointer, TIntObjectHashMap stringTable, + boolean onlyDescription) throws IOException { + codedIS.seek(filePointer); + int routeLength = codedIS.readRawVarint32(); + int old = codedIS.pushLimit(routeLength); + net.osmand.data.TransportRoute dataObject = new net.osmand.data.TransportRoute(); + boolean end = false; + long rid = 0; + int rx = 0; + int ry = 0; + long did = 0; + int dx = 0; + int dy = 0; + while(!end){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + end = true; + break; + case OsmandOdb.TransportRoute.DISTANCE_FIELD_NUMBER : + dataObject.setDistance(codedIS.readUInt32()); + break; + case OsmandOdb.TransportRoute.ID_FIELD_NUMBER : + dataObject.setId(codedIS.readUInt64()); + break; + case OsmandOdb.TransportRoute.REF_FIELD_NUMBER : + dataObject.setRef(codedIS.readString()); + break; + case OsmandOdb.TransportRoute.TYPE_FIELD_NUMBER : + dataObject.setType(regStr(stringTable)); //$NON-NLS-1$ + break; + case OsmandOdb.TransportRoute.NAME_EN_FIELD_NUMBER : + dataObject.setEnName(regStr(stringTable)); //$NON-NLS-1$ + break; + case OsmandOdb.TransportRoute.NAME_FIELD_NUMBER : + dataObject.setName(regStr(stringTable)); //$NON-NLS-1$ + break; + case OsmandOdb.TransportRoute.OPERATOR_FIELD_NUMBER: + dataObject.setOperator(regStr(stringTable)); //$NON-NLS-1$ + break; + case OsmandOdb.TransportRoute.REVERSESTOPS_FIELD_NUMBER: + if(onlyDescription){ + end = true; + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + break; + } + int length = codedIS.readRawVarint32(); + int olds = codedIS.pushLimit(length); + TransportStop stop = readTransportRouteStop(dx, dy, did, stringTable); + dataObject.getBackwardStops().add(stop); + did = stop.getId(); + dx = (int) MapUtils.getTileNumberX(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, stop.getLocation().getLongitude()); + dy = (int) MapUtils.getTileNumberY(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, stop.getLocation().getLatitude()); + codedIS.popLimit(olds); + break; + case OsmandOdb.TransportRoute.DIRECTSTOPS_FIELD_NUMBER: + if(onlyDescription){ + end = true; + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + break; + } + length = codedIS.readRawVarint32(); + olds = codedIS.pushLimit(length); + stop = readTransportRouteStop(rx, ry, rid, stringTable); + dataObject.getForwardStops().add(stop); + rid = stop.getId(); + rx = (int) MapUtils.getTileNumberX(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, stop.getLocation().getLongitude()); + ry = (int) MapUtils.getTileNumberY(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, stop.getLocation().getLatitude()); + codedIS.popLimit(olds); + break; + default: + skipUnknownField(t); + break; + } + } + codedIS.popLimit(old); + + + return dataObject; + } + + protected void initializeStringTable(TransportIndex ind, TIntObjectHashMap stringTable) throws IOException { + int[] values = stringTable.keys(); + Arrays.sort(values); + codedIS.seek(ind.stringTable.fileOffset); + int oldLimit = codedIS.pushLimit(ind.stringTable.length); + int current = 0; + int i = 0; + while (i < values.length) { + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + break; + case OsmandOdb.StringTable.S_FIELD_NUMBER: + if (current == values[i]) { + String value = codedIS.readString(); + stringTable.put(values[i], value); + i++; + } else { + skipUnknownField(t); + } + current ++; + break; + default: + skipUnknownField(t); + break; + } + } + codedIS.popLimit(oldLimit); + } + + protected void initializeNames(boolean onlyDescription, net.osmand.data.TransportRoute dataObject, + TIntObjectHashMap stringTable) throws IOException { + if(dataObject.getName().length() > 0){ + dataObject.setName(stringTable.get(dataObject.getName().charAt(0))); + } + if(dataObject.getEnName().length() > 0){ + dataObject.setEnName(stringTable.get(dataObject.getEnName().charAt(0))); + } + if(dataObject.getName().length() > 0 && dataObject.getEnName().length() == 0){ + dataObject.setEnName(Junidecode.unidecode(dataObject.getName())); + } + + if(dataObject.getOperator().length() > 0){ + dataObject.setOperator(stringTable.get(dataObject.getOperator().charAt(0))); + } + if(dataObject.getType().length() > 0){ + dataObject.setType(stringTable.get(dataObject.getType().charAt(0))); + } + for (int i = 0; i < 2 && !onlyDescription; i++) { + List stops = i == 0 ? dataObject.getForwardStops() : dataObject.getBackwardStops(); + for (TransportStop s : stops) { + initializeNames(stringTable, s); + } + } + } + + protected void initializeNames(TIntObjectHashMap stringTable, TransportStop s) { + if (s.getName().length() > 0) { + s.setName(stringTable.get(s.getName().charAt(0))); + } + if (s.getEnName().length() > 0) { + s.setEnName(stringTable.get(s.getEnName().charAt(0))); + } + if (s.getEnName().length() == 0) { + s.setEnName(Junidecode.unidecode(s.getName())); + } + } + + + + private TransportStop readTransportRouteStop(int dx, int dy, long did, TIntObjectHashMap stringTable) throws IOException { + TransportStop dataObject = new TransportStop(); + boolean end = false; + while(!end){ + int t = codedIS.readTag(); + int tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + end = true; + break; + case OsmandOdb.TransportRouteStop.NAME_EN_FIELD_NUMBER : + dataObject.setEnName(regStr(stringTable)); //$NON-NLS-1$ + break; + case OsmandOdb.TransportRouteStop.NAME_FIELD_NUMBER : + dataObject.setName(regStr(stringTable)); //$NON-NLS-1$ + break; + case OsmandOdb.TransportRouteStop.ID_FIELD_NUMBER : + did += codedIS.readSInt64(); + break; + case OsmandOdb.TransportRouteStop.DX_FIELD_NUMBER : + dx += codedIS.readSInt32(); + break; + case OsmandOdb.TransportRouteStop.DY_FIELD_NUMBER : + dy += codedIS.readSInt32(); + break; + default: + skipUnknownField(t); + break; + } + } + dataObject.setId(did); + dataObject.setLocation(MapUtils.getLatitudeFromTile(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, dy), MapUtils.getLongitudeFromTile(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, dx)); + return dataObject; + } + + private TransportStop readTransportStop(int shift, int cleft, int cright, int ctop, int cbottom, SearchRequest req) throws IOException { + int tag = WireFormat.getTagFieldNumber(codedIS.readTag()); + if(OsmandOdb.TransportStop.DX_FIELD_NUMBER != tag) { + throw new IllegalArgumentException(); + } + int x = codedIS.readSInt32() + cleft; + + tag = WireFormat.getTagFieldNumber(codedIS.readTag()); + if(OsmandOdb.TransportStop.DY_FIELD_NUMBER != tag) { + throw new IllegalArgumentException(); + } + int y = codedIS.readSInt32() + ctop; + if(req.right < x || req.left > x || req.top > y || req.bottom < y){ + codedIS.skipRawBytes(codedIS.getBytesUntilLimit()); + return null; + } + + req.numberOfAcceptedObjects++; + req.cacheTypes.clear(); + + TransportStop dataObject = new TransportStop(); + dataObject.setLocation(MapUtils.getLatitudeFromTile(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, y), MapUtils.getLongitudeFromTile(BinaryMapIndexReader.TRANSPORT_STOP_ZOOM, x)); + dataObject.setFileOffset(shift); + while(true){ + int t = codedIS.readTag(); + tag = WireFormat.getTagFieldNumber(t); + switch (tag) { + case 0: + dataObject.setReferencesToRoutes(req.cacheTypes.toArray()); + if(dataObject.getEnName().length() == 0){ + dataObject.setEnName(Junidecode.unidecode(dataObject.getName())); + } + return dataObject; + case OsmandOdb.TransportStop.ROUTES_FIELD_NUMBER : + req.cacheTypes.add(shift - codedIS.readUInt32()); + break; + case OsmandOdb.TransportStop.NAME_EN_FIELD_NUMBER : + if (req.stringTable != null) { + dataObject.setEnName(regStr(req.stringTable)); //$NON-NLS-1$ + } else { + skipUnknownField(t); + } + break; + case OsmandOdb.TransportStop.NAME_FIELD_NUMBER : + if (req.stringTable != null) { + dataObject.setName(regStr(req.stringTable)); //$NON-NLS-1$ + } else { + skipUnknownField(t); + } + + break; + case OsmandOdb.TransportStop.ID_FIELD_NUMBER : + dataObject.setId(codedIS.readSInt64()); + break; + default: + skipUnknownField(t); + break; + } + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/binary/CachedOsmandIndexes.java b/OsmAnd-java/src/net/osmand/binary/CachedOsmandIndexes.java new file mode 100644 index 0000000000..7336fc7aee --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/CachedOsmandIndexes.java @@ -0,0 +1,327 @@ +package net.osmand.binary; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +import net.osmand.PlatformUtil; +import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion; +import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock; +import net.osmand.binary.BinaryMapIndexReader.MapIndex; +import net.osmand.binary.BinaryMapIndexReader.MapRoot; +import net.osmand.binary.BinaryMapPoiReaderAdapter.PoiRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; +import net.osmand.binary.BinaryMapTransportReaderAdapter.IndexStringTable; +import net.osmand.binary.BinaryMapTransportReaderAdapter.TransportIndex; +import net.osmand.binary.OsmandIndex.AddressPart; +import net.osmand.binary.OsmandIndex.CityBlock; +import net.osmand.binary.OsmandIndex.FileIndex; +import net.osmand.binary.OsmandIndex.MapLevel; +import net.osmand.binary.OsmandIndex.MapPart; +import net.osmand.binary.OsmandIndex.OsmAndStoredIndex; +import net.osmand.binary.OsmandIndex.PoiPart; +import net.osmand.binary.OsmandIndex.RoutingPart; +import net.osmand.binary.OsmandIndex.RoutingSubregion; +import net.osmand.binary.OsmandIndex.TransportPart; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +public class CachedOsmandIndexes { + + private OsmAndStoredIndex storedIndex; + private OsmAndStoredIndex.Builder storedIndexBuilder; + private Log log = PlatformUtil.getLog(CachedOsmandIndexes.class); + private boolean hasChanged = true; + + public static final int VERSION = 2; + + public void addToCache(BinaryMapIndexReader reader, File f) { + hasChanged = true; + if(storedIndexBuilder == null) { + storedIndexBuilder = OsmandIndex.OsmAndStoredIndex.newBuilder(); + storedIndexBuilder.setVersion(VERSION); + storedIndexBuilder.setDateCreated(System.currentTimeMillis()); + if(storedIndex != null) { + for(FileIndex ex : storedIndex.getFileIndexList()) { + storedIndexBuilder.addFileIndex(ex); + } + } + } + + FileIndex.Builder fileIndex = OsmandIndex.FileIndex.newBuilder(); + long d = reader.getDateCreated(); + fileIndex.setDateModified(d== 0?f.lastModified() : d); + fileIndex.setSize(f.length()); + fileIndex.setVersion(reader.getVersion()); + fileIndex.setFileName(f.getName()); + for(MapIndex index : reader.getMapIndexes()) { + MapPart.Builder map = OsmandIndex.MapPart.newBuilder(); + map.setSize(index.getLength()); + map.setOffset(index.getFilePointer()); + if(index.getName() != null) { + map.setName(index.getName()); + } + for(MapRoot mr : index.getRoots() ) { + MapLevel.Builder lev = OsmandIndex.MapLevel.newBuilder(); + lev.setSize(mr.length); + lev.setOffset(mr.filePointer); + lev.setLeft(mr.left); + lev.setRight(mr.right); + lev.setTop(mr.top); + lev.setBottom(mr.bottom); + lev.setMinzoom(mr.minZoom); + lev.setMaxzoom(mr.maxZoom); + map.addLevels(lev); + } + fileIndex.addMapIndex(map); + } + + for(AddressRegion index : reader.getAddressIndexes()) { + AddressPart.Builder addr = OsmandIndex.AddressPart.newBuilder(); + addr.setSize(index.getLength()); + addr.setOffset(index.getFilePointer()); + if(index.getName() != null) { + addr.setName(index.getName()); + } + if(index.getEnName() != null) { + addr.setNameEn(index.getEnName()); + } + addr.setIndexNameOffset(index.getIndexNameOffset()); + for(CitiesBlock mr : index.getCities() ) { + CityBlock.Builder cblock = OsmandIndex.CityBlock.newBuilder(); + cblock.setSize(mr.length); + cblock.setOffset(mr.filePointer); + cblock.setType(mr.type); + addr.addCities(cblock); + } + fileIndex.addAddressIndex(addr); + } + + for(PoiRegion index : reader.getPoiIndexes()) { + PoiPart.Builder poi = OsmandIndex.PoiPart.newBuilder(); + poi.setSize(index.getLength()); + poi.setOffset(index.getFilePointer()); + if(index.getName() != null) { + poi.setName(index.getName()); + } + poi.setLeft(MapUtils.get31TileNumberX(index.getLeftLongitude())); + poi.setRight(MapUtils.get31TileNumberX(index.getRightLongitude())); + poi.setTop(MapUtils.get31TileNumberY(index.getTopLatitude())); + poi.setBottom(MapUtils.get31TileNumberY(index.getBottomLatitude())); + fileIndex.addPoiIndex(poi.build()); + } + + for(TransportIndex index : reader.getTransportIndexes()) { + TransportPart.Builder transport = OsmandIndex.TransportPart.newBuilder(); + transport.setSize(index.getLength()); + transport.setOffset(index.getFilePointer()); + if(index.getName() != null) { + transport.setName(index.getName()); + } + transport.setLeft(index.getLeft()); + transport.setRight(index.getRight()); + transport.setTop(index.getTop()); + transport.setBottom(index.getBottom()); + transport.setStopsTableLength(index.stopsFileLength); + transport.setStopsTableOffset(index.stopsFileOffset); + transport.setStringTableLength(index.stringTable.length); + transport.setStringTableOffset(index.stringTable.fileOffset); + fileIndex.addTransportIndex(transport); + } + + for(RouteRegion index : reader.getRoutingIndexes()) { + RoutingPart.Builder routing = OsmandIndex.RoutingPart.newBuilder(); + routing.setSize(index.getLength()); + routing.setOffset(index.getFilePointer()); + if(index.getName() != null) { + routing.setName(index.getName()); + } + for(RouteSubregion sub : index.getSubregions()) { + addRouteSubregion(routing, sub, false); + } + for(RouteSubregion sub : index.getBaseSubregions()) { + addRouteSubregion(routing, sub, true); + } + fileIndex.addRoutingIndex(routing); + } + + storedIndexBuilder.addFileIndex(fileIndex); + + } + + private void addRouteSubregion(RoutingPart.Builder routing, RouteSubregion sub, boolean base) { + OsmandIndex.RoutingSubregion.Builder rpart = OsmandIndex.RoutingSubregion.newBuilder(); + rpart.setSize(sub.length); + rpart.setOffset(sub.filePointer); + rpart.setLeft(sub.left); + rpart.setRight(sub.right); + rpart.setTop(sub.top); + rpart.setBasemap(base); + rpart.setBottom(sub.bottom); + rpart.setShifToData(sub.shiftToData); + routing.addSubregions(rpart); + } + + public BinaryMapIndexReader getReader(File f) throws IOException { + RandomAccessFile mf = new RandomAccessFile(f.getPath(), "r"); + FileIndex found = null; + if (storedIndex != null) { + for (int i = 0; i < storedIndex.getFileIndexCount(); i++) { + FileIndex fi = storedIndex.getFileIndex(i); + if (f.length() == fi.getSize() && f.getName().equals(fi.getFileName())) { + // f.lastModified() == fi.getDateModified() + found = fi; + break; + } + } + } + BinaryMapIndexReader reader = null; + if (found == null) { + long val = System.currentTimeMillis(); + reader = new BinaryMapIndexReader(mf); + addToCache(reader, f); + if (log.isDebugEnabled()) { + log.debug("Initializing db " + f.getAbsolutePath() + " " + (System.currentTimeMillis() - val ) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } else { + reader = initFileIndex(found, mf); + } + return reader; + } + + private BinaryMapIndexReader initFileIndex(FileIndex found, RandomAccessFile mf) throws IOException { + BinaryMapIndexReader reader = new BinaryMapIndexReader(mf, false); + reader.version = found.getVersion(); + reader.dateCreated = found.getDateModified(); + + for(MapPart index : found.getMapIndexList()) { + MapIndex mi = new MapIndex(); + mi.length = (int) index.getSize(); + mi.filePointer = (int) index.getOffset(); + mi.name = index.getName(); + + for(MapLevel mr : index.getLevelsList()) { + MapRoot root = new MapRoot(); + root.length = (int) mr.getSize(); + root.filePointer = (int) mr.getOffset(); + root.left = mr.getLeft(); + root.right = mr.getRight(); + root.top = mr.getTop(); + root.bottom = mr.getBottom(); + root.minZoom = mr.getMinzoom(); + root.maxZoom = mr.getMaxzoom(); + mi.roots.add(root); + } + reader.mapIndexes.add(mi); + reader.indexes.add(mi); + reader.basemap = reader.basemap || mi.isBaseMap(); + } + + for(AddressPart index : found.getAddressIndexList()) { + AddressRegion mi = new AddressRegion(); + mi.length = (int) index.getSize(); + mi.filePointer = (int) index.getOffset(); + mi.name = index.getName(); + mi.enName = index.getNameEn(); + mi.indexNameOffset = index.getIndexNameOffset(); + for(CityBlock mr : index.getCitiesList() ) { + CitiesBlock cblock = new CitiesBlock(); + cblock.length = (int) mr.getSize(); + cblock.filePointer = (int) mr.getOffset(); + cblock.type = mr.getType(); + mi.cities.add(cblock); + } + reader.addressIndexes.add(mi); + reader.indexes.add(mi); + } + + for(PoiPart index : found.getPoiIndexList()) { + PoiRegion mi = new PoiRegion(); + mi.length = (int) index.getSize(); + mi.filePointer = (int) index.getOffset(); + mi.name = index.getName(); + mi.leftLongitude = MapUtils.get31LongitudeX(index.getLeft()); + mi.rightLongitude = MapUtils.get31LongitudeX(index.getRight()); + mi.topLatitude =MapUtils.get31LatitudeY(index.getTop()); + mi.bottomLatitude = MapUtils.get31LatitudeY(index.getBottom()); + reader.poiIndexes.add(mi); + reader.indexes.add(mi); + } + + for(TransportPart index : found.getTransportIndexList()) { + TransportIndex mi = new TransportIndex(); + mi.length = (int) index.getSize(); + mi.filePointer = (int) index.getOffset(); + mi.name = index.getName(); + mi.left = index.getLeft(); + mi.right =index.getRight(); + mi.top = index.getTop(); + mi.bottom = index.getBottom(); + mi.stopsFileLength = index.getStopsTableLength(); + mi.stopsFileOffset = index.getStopsTableOffset(); + mi.stringTable = new IndexStringTable(); + mi.stringTable.fileOffset = index.getStringTableOffset(); + mi.stringTable.length = index.getStringTableLength(); + reader.transportIndexes.add(mi); + reader.indexes.add(mi); + } + + for(RoutingPart index : found.getRoutingIndexList()) { + RouteRegion mi = new RouteRegion(); + mi.length = (int) index.getSize(); + mi.filePointer = (int) index.getOffset(); + mi.name = index.getName(); + + for(RoutingSubregion mr : index.getSubregionsList()) { + RouteSubregion sub = new RouteSubregion(mi); + sub.length = (int) mr.getSize(); + sub.filePointer = (int) mr.getOffset(); + sub.left = mr.getLeft(); + sub.right = mr.getRight(); + sub.top = mr.getTop(); + sub.bottom = mr.getBottom(); + sub.shiftToData = mr.getShifToData(); + if(mr.getBasemap()) { + mi.basesubregions.add(sub); + } else { + mi.subregions.add(sub); + } + } + reader.routingIndexes.add(mi); + reader.indexes.add(mi); + } + + return reader; + } + + public void readFromFile(File f, int version) throws IOException { + long time = System.currentTimeMillis(); + FileInputStream is = new FileInputStream(f); + try { + storedIndex = OsmandIndex.OsmAndStoredIndex.newBuilder().mergeFrom(is).build(); + hasChanged = false; + if(storedIndex.getVersion() != version){ + storedIndex = null; + } + } finally { + is.close(); + } + log.info("Initialize cache " + (System.currentTimeMillis() - time)); + } + + public void writeToFile(File f) throws IOException { + if (hasChanged) { + FileOutputStream outputStream = new FileOutputStream(f); + try { + storedIndexBuilder.build().writeTo(outputStream); + } finally { + outputStream.close(); + } + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/binary/OsmandIndex.java b/OsmAnd-java/src/net/osmand/binary/OsmandIndex.java new file mode 100644 index 0000000000..ddfc7adf4a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/OsmandIndex.java @@ -0,0 +1,5262 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: DataExtractionOSM/src/osmand_index.proto + +package net.osmand.binary; + +public final class OsmandIndex { + private OsmandIndex() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + public static final class OsmAndStoredIndex extends + com.google.protobuf.GeneratedMessageLite { + // Use OsmAndStoredIndex.newBuilder() to construct. + private OsmAndStoredIndex() { + initFields(); + } + private OsmAndStoredIndex(boolean noInit) {} + + private static final OsmAndStoredIndex defaultInstance; + public static OsmAndStoredIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndStoredIndex getDefaultInstanceForType() { + return defaultInstance; + } + + // required uint32 version = 1; + public static final int VERSION_FIELD_NUMBER = 1; + private boolean hasVersion; + private int version_ = 0; + public boolean hasVersion() { return hasVersion; } + public int getVersion() { return version_; } + + // required int64 dateCreated = 18; + public static final int DATECREATED_FIELD_NUMBER = 18; + private boolean hasDateCreated; + private long dateCreated_ = 0L; + public boolean hasDateCreated() { return hasDateCreated; } + public long getDateCreated() { return dateCreated_; } + + // repeated .FileIndex fileIndex = 7; + public static final int FILEINDEX_FIELD_NUMBER = 7; + private java.util.List fileIndex_ = + java.util.Collections.emptyList(); + public java.util.List getFileIndexList() { + return fileIndex_; + } + public int getFileIndexCount() { return fileIndex_.size(); } + public net.osmand.binary.OsmandIndex.FileIndex getFileIndex(int index) { + return fileIndex_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasVersion) return false; + if (!hasDateCreated) return false; + for (net.osmand.binary.OsmandIndex.FileIndex element : getFileIndexList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasVersion()) { + output.writeUInt32(1, getVersion()); + } + for (net.osmand.binary.OsmandIndex.FileIndex element : getFileIndexList()) { + output.writeMessage(7, element); + } + if (hasDateCreated()) { + output.writeInt64(18, getDateCreated()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasVersion()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, getVersion()); + } + for (net.osmand.binary.OsmandIndex.FileIndex element : getFileIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + if (hasDateCreated()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(18, getDateCreated()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.OsmAndStoredIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.OsmAndStoredIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.OsmAndStoredIndex, Builder> { + private net.osmand.binary.OsmandIndex.OsmAndStoredIndex result; + + // Construct using net.osmand.binary.OsmandIndex.OsmAndStoredIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.OsmAndStoredIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.OsmAndStoredIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.OsmAndStoredIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.OsmAndStoredIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.OsmAndStoredIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.OsmAndStoredIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.OsmAndStoredIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.OsmAndStoredIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.fileIndex_ != java.util.Collections.EMPTY_LIST) { + result.fileIndex_ = + java.util.Collections.unmodifiableList(result.fileIndex_); + } + net.osmand.binary.OsmandIndex.OsmAndStoredIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.OsmAndStoredIndex other) { + if (other == net.osmand.binary.OsmandIndex.OsmAndStoredIndex.getDefaultInstance()) return this; + if (other.hasVersion()) { + setVersion(other.getVersion()); + } + if (other.hasDateCreated()) { + setDateCreated(other.getDateCreated()); + } + if (!other.fileIndex_.isEmpty()) { + if (result.fileIndex_.isEmpty()) { + result.fileIndex_ = new java.util.ArrayList(); + } + result.fileIndex_.addAll(other.fileIndex_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setVersion(input.readUInt32()); + break; + } + case 58: { + net.osmand.binary.OsmandIndex.FileIndex.Builder subBuilder = net.osmand.binary.OsmandIndex.FileIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addFileIndex(subBuilder.buildPartial()); + break; + } + case 144: { + setDateCreated(input.readInt64()); + break; + } + } + } + } + + + // required uint32 version = 1; + public boolean hasVersion() { + return result.hasVersion(); + } + public int getVersion() { + return result.getVersion(); + } + public Builder setVersion(int value) { + result.hasVersion = true; + result.version_ = value; + return this; + } + public Builder clearVersion() { + result.hasVersion = false; + result.version_ = 0; + return this; + } + + // required int64 dateCreated = 18; + public boolean hasDateCreated() { + return result.hasDateCreated(); + } + public long getDateCreated() { + return result.getDateCreated(); + } + public Builder setDateCreated(long value) { + result.hasDateCreated = true; + result.dateCreated_ = value; + return this; + } + public Builder clearDateCreated() { + result.hasDateCreated = false; + result.dateCreated_ = 0L; + return this; + } + + // repeated .FileIndex fileIndex = 7; + public java.util.List getFileIndexList() { + return java.util.Collections.unmodifiableList(result.fileIndex_); + } + public int getFileIndexCount() { + return result.getFileIndexCount(); + } + public net.osmand.binary.OsmandIndex.FileIndex getFileIndex(int index) { + return result.getFileIndex(index); + } + public Builder setFileIndex(int index, net.osmand.binary.OsmandIndex.FileIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.fileIndex_.set(index, value); + return this; + } + public Builder setFileIndex(int index, net.osmand.binary.OsmandIndex.FileIndex.Builder builderForValue) { + result.fileIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addFileIndex(net.osmand.binary.OsmandIndex.FileIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.fileIndex_.isEmpty()) { + result.fileIndex_ = new java.util.ArrayList(); + } + result.fileIndex_.add(value); + return this; + } + public Builder addFileIndex(net.osmand.binary.OsmandIndex.FileIndex.Builder builderForValue) { + if (result.fileIndex_.isEmpty()) { + result.fileIndex_ = new java.util.ArrayList(); + } + result.fileIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllFileIndex( + java.lang.Iterable values) { + if (result.fileIndex_.isEmpty()) { + result.fileIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.fileIndex_); + return this; + } + public Builder clearFileIndex() { + result.fileIndex_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndStoredIndex) + } + + static { + defaultInstance = new OsmAndStoredIndex(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndStoredIndex) + } + + public static final class FileIndex extends + com.google.protobuf.GeneratedMessageLite { + // Use FileIndex.newBuilder() to construct. + private FileIndex() { + initFields(); + } + private FileIndex(boolean noInit) {} + + private static final FileIndex defaultInstance; + public static FileIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public FileIndex getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 dateModified = 2; + public static final int DATEMODIFIED_FIELD_NUMBER = 2; + private boolean hasDateModified; + private long dateModified_ = 0L; + public boolean hasDateModified() { return hasDateModified; } + public long getDateModified() { return dateModified_; } + + // required string fileName = 3; + public static final int FILENAME_FIELD_NUMBER = 3; + private boolean hasFileName; + private java.lang.String fileName_ = ""; + public boolean hasFileName() { return hasFileName; } + public java.lang.String getFileName() { return fileName_; } + + // required int32 version = 4; + public static final int VERSION_FIELD_NUMBER = 4; + private boolean hasVersion; + private int version_ = 0; + public boolean hasVersion() { return hasVersion; } + public int getVersion() { return version_; } + + // repeated .AddressPart addressIndex = 8; + public static final int ADDRESSINDEX_FIELD_NUMBER = 8; + private java.util.List addressIndex_ = + java.util.Collections.emptyList(); + public java.util.List getAddressIndexList() { + return addressIndex_; + } + public int getAddressIndexCount() { return addressIndex_.size(); } + public net.osmand.binary.OsmandIndex.AddressPart getAddressIndex(int index) { + return addressIndex_.get(index); + } + + // repeated .TransportPart transportIndex = 9; + public static final int TRANSPORTINDEX_FIELD_NUMBER = 9; + private java.util.List transportIndex_ = + java.util.Collections.emptyList(); + public java.util.List getTransportIndexList() { + return transportIndex_; + } + public int getTransportIndexCount() { return transportIndex_.size(); } + public net.osmand.binary.OsmandIndex.TransportPart getTransportIndex(int index) { + return transportIndex_.get(index); + } + + // repeated .PoiPart poiIndex = 10; + public static final int POIINDEX_FIELD_NUMBER = 10; + private java.util.List poiIndex_ = + java.util.Collections.emptyList(); + public java.util.List getPoiIndexList() { + return poiIndex_; + } + public int getPoiIndexCount() { return poiIndex_.size(); } + public net.osmand.binary.OsmandIndex.PoiPart getPoiIndex(int index) { + return poiIndex_.get(index); + } + + // repeated .MapPart mapIndex = 11; + public static final int MAPINDEX_FIELD_NUMBER = 11; + private java.util.List mapIndex_ = + java.util.Collections.emptyList(); + public java.util.List getMapIndexList() { + return mapIndex_; + } + public int getMapIndexCount() { return mapIndex_.size(); } + public net.osmand.binary.OsmandIndex.MapPart getMapIndex(int index) { + return mapIndex_.get(index); + } + + // repeated .RoutingPart routingIndex = 12; + public static final int ROUTINGINDEX_FIELD_NUMBER = 12; + private java.util.List routingIndex_ = + java.util.Collections.emptyList(); + public java.util.List getRoutingIndexList() { + return routingIndex_; + } + public int getRoutingIndexCount() { return routingIndex_.size(); } + public net.osmand.binary.OsmandIndex.RoutingPart getRoutingIndex(int index) { + return routingIndex_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasDateModified) return false; + if (!hasFileName) return false; + if (!hasVersion) return false; + for (net.osmand.binary.OsmandIndex.AddressPart element : getAddressIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandIndex.TransportPart element : getTransportIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandIndex.PoiPart element : getPoiIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandIndex.MapPart element : getMapIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandIndex.RoutingPart element : getRoutingIndexList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasDateModified()) { + output.writeInt64(2, getDateModified()); + } + if (hasFileName()) { + output.writeString(3, getFileName()); + } + if (hasVersion()) { + output.writeInt32(4, getVersion()); + } + for (net.osmand.binary.OsmandIndex.AddressPart element : getAddressIndexList()) { + output.writeMessage(8, element); + } + for (net.osmand.binary.OsmandIndex.TransportPart element : getTransportIndexList()) { + output.writeMessage(9, element); + } + for (net.osmand.binary.OsmandIndex.PoiPart element : getPoiIndexList()) { + output.writeMessage(10, element); + } + for (net.osmand.binary.OsmandIndex.MapPart element : getMapIndexList()) { + output.writeMessage(11, element); + } + for (net.osmand.binary.OsmandIndex.RoutingPart element : getRoutingIndexList()) { + output.writeMessage(12, element); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasDateModified()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getDateModified()); + } + if (hasFileName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getFileName()); + } + if (hasVersion()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getVersion()); + } + for (net.osmand.binary.OsmandIndex.AddressPart element : getAddressIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, element); + } + for (net.osmand.binary.OsmandIndex.TransportPart element : getTransportIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, element); + } + for (net.osmand.binary.OsmandIndex.PoiPart element : getPoiIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(10, element); + } + for (net.osmand.binary.OsmandIndex.MapPart element : getMapIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(11, element); + } + for (net.osmand.binary.OsmandIndex.RoutingPart element : getRoutingIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(12, element); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.FileIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.FileIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.FileIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.FileIndex, Builder> { + private net.osmand.binary.OsmandIndex.FileIndex result; + + // Construct using net.osmand.binary.OsmandIndex.FileIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.FileIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.FileIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.FileIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.FileIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.FileIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.FileIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.FileIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.FileIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.addressIndex_ != java.util.Collections.EMPTY_LIST) { + result.addressIndex_ = + java.util.Collections.unmodifiableList(result.addressIndex_); + } + if (result.transportIndex_ != java.util.Collections.EMPTY_LIST) { + result.transportIndex_ = + java.util.Collections.unmodifiableList(result.transportIndex_); + } + if (result.poiIndex_ != java.util.Collections.EMPTY_LIST) { + result.poiIndex_ = + java.util.Collections.unmodifiableList(result.poiIndex_); + } + if (result.mapIndex_ != java.util.Collections.EMPTY_LIST) { + result.mapIndex_ = + java.util.Collections.unmodifiableList(result.mapIndex_); + } + if (result.routingIndex_ != java.util.Collections.EMPTY_LIST) { + result.routingIndex_ = + java.util.Collections.unmodifiableList(result.routingIndex_); + } + net.osmand.binary.OsmandIndex.FileIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.FileIndex other) { + if (other == net.osmand.binary.OsmandIndex.FileIndex.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasDateModified()) { + setDateModified(other.getDateModified()); + } + if (other.hasFileName()) { + setFileName(other.getFileName()); + } + if (other.hasVersion()) { + setVersion(other.getVersion()); + } + if (!other.addressIndex_.isEmpty()) { + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + result.addressIndex_.addAll(other.addressIndex_); + } + if (!other.transportIndex_.isEmpty()) { + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + result.transportIndex_.addAll(other.transportIndex_); + } + if (!other.poiIndex_.isEmpty()) { + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + result.poiIndex_.addAll(other.poiIndex_); + } + if (!other.mapIndex_.isEmpty()) { + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + result.mapIndex_.addAll(other.mapIndex_); + } + if (!other.routingIndex_.isEmpty()) { + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + result.routingIndex_.addAll(other.routingIndex_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setDateModified(input.readInt64()); + break; + } + case 26: { + setFileName(input.readString()); + break; + } + case 32: { + setVersion(input.readInt32()); + break; + } + case 66: { + net.osmand.binary.OsmandIndex.AddressPart.Builder subBuilder = net.osmand.binary.OsmandIndex.AddressPart.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addAddressIndex(subBuilder.buildPartial()); + break; + } + case 74: { + net.osmand.binary.OsmandIndex.TransportPart.Builder subBuilder = net.osmand.binary.OsmandIndex.TransportPart.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addTransportIndex(subBuilder.buildPartial()); + break; + } + case 82: { + net.osmand.binary.OsmandIndex.PoiPart.Builder subBuilder = net.osmand.binary.OsmandIndex.PoiPart.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPoiIndex(subBuilder.buildPartial()); + break; + } + case 90: { + net.osmand.binary.OsmandIndex.MapPart.Builder subBuilder = net.osmand.binary.OsmandIndex.MapPart.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addMapIndex(subBuilder.buildPartial()); + break; + } + case 98: { + net.osmand.binary.OsmandIndex.RoutingPart.Builder subBuilder = net.osmand.binary.OsmandIndex.RoutingPart.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRoutingIndex(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 dateModified = 2; + public boolean hasDateModified() { + return result.hasDateModified(); + } + public long getDateModified() { + return result.getDateModified(); + } + public Builder setDateModified(long value) { + result.hasDateModified = true; + result.dateModified_ = value; + return this; + } + public Builder clearDateModified() { + result.hasDateModified = false; + result.dateModified_ = 0L; + return this; + } + + // required string fileName = 3; + public boolean hasFileName() { + return result.hasFileName(); + } + public java.lang.String getFileName() { + return result.getFileName(); + } + public Builder setFileName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasFileName = true; + result.fileName_ = value; + return this; + } + public Builder clearFileName() { + result.hasFileName = false; + result.fileName_ = getDefaultInstance().getFileName(); + return this; + } + + // required int32 version = 4; + public boolean hasVersion() { + return result.hasVersion(); + } + public int getVersion() { + return result.getVersion(); + } + public Builder setVersion(int value) { + result.hasVersion = true; + result.version_ = value; + return this; + } + public Builder clearVersion() { + result.hasVersion = false; + result.version_ = 0; + return this; + } + + // repeated .AddressPart addressIndex = 8; + public java.util.List getAddressIndexList() { + return java.util.Collections.unmodifiableList(result.addressIndex_); + } + public int getAddressIndexCount() { + return result.getAddressIndexCount(); + } + public net.osmand.binary.OsmandIndex.AddressPart getAddressIndex(int index) { + return result.getAddressIndex(index); + } + public Builder setAddressIndex(int index, net.osmand.binary.OsmandIndex.AddressPart value) { + if (value == null) { + throw new NullPointerException(); + } + result.addressIndex_.set(index, value); + return this; + } + public Builder setAddressIndex(int index, net.osmand.binary.OsmandIndex.AddressPart.Builder builderForValue) { + result.addressIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addAddressIndex(net.osmand.binary.OsmandIndex.AddressPart value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + result.addressIndex_.add(value); + return this; + } + public Builder addAddressIndex(net.osmand.binary.OsmandIndex.AddressPart.Builder builderForValue) { + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + result.addressIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllAddressIndex( + java.lang.Iterable values) { + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.addressIndex_); + return this; + } + public Builder clearAddressIndex() { + result.addressIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .TransportPart transportIndex = 9; + public java.util.List getTransportIndexList() { + return java.util.Collections.unmodifiableList(result.transportIndex_); + } + public int getTransportIndexCount() { + return result.getTransportIndexCount(); + } + public net.osmand.binary.OsmandIndex.TransportPart getTransportIndex(int index) { + return result.getTransportIndex(index); + } + public Builder setTransportIndex(int index, net.osmand.binary.OsmandIndex.TransportPart value) { + if (value == null) { + throw new NullPointerException(); + } + result.transportIndex_.set(index, value); + return this; + } + public Builder setTransportIndex(int index, net.osmand.binary.OsmandIndex.TransportPart.Builder builderForValue) { + result.transportIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addTransportIndex(net.osmand.binary.OsmandIndex.TransportPart value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + result.transportIndex_.add(value); + return this; + } + public Builder addTransportIndex(net.osmand.binary.OsmandIndex.TransportPart.Builder builderForValue) { + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + result.transportIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllTransportIndex( + java.lang.Iterable values) { + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.transportIndex_); + return this; + } + public Builder clearTransportIndex() { + result.transportIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .PoiPart poiIndex = 10; + public java.util.List getPoiIndexList() { + return java.util.Collections.unmodifiableList(result.poiIndex_); + } + public int getPoiIndexCount() { + return result.getPoiIndexCount(); + } + public net.osmand.binary.OsmandIndex.PoiPart getPoiIndex(int index) { + return result.getPoiIndex(index); + } + public Builder setPoiIndex(int index, net.osmand.binary.OsmandIndex.PoiPart value) { + if (value == null) { + throw new NullPointerException(); + } + result.poiIndex_.set(index, value); + return this; + } + public Builder setPoiIndex(int index, net.osmand.binary.OsmandIndex.PoiPart.Builder builderForValue) { + result.poiIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addPoiIndex(net.osmand.binary.OsmandIndex.PoiPart value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + result.poiIndex_.add(value); + return this; + } + public Builder addPoiIndex(net.osmand.binary.OsmandIndex.PoiPart.Builder builderForValue) { + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + result.poiIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllPoiIndex( + java.lang.Iterable values) { + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.poiIndex_); + return this; + } + public Builder clearPoiIndex() { + result.poiIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .MapPart mapIndex = 11; + public java.util.List getMapIndexList() { + return java.util.Collections.unmodifiableList(result.mapIndex_); + } + public int getMapIndexCount() { + return result.getMapIndexCount(); + } + public net.osmand.binary.OsmandIndex.MapPart getMapIndex(int index) { + return result.getMapIndex(index); + } + public Builder setMapIndex(int index, net.osmand.binary.OsmandIndex.MapPart value) { + if (value == null) { + throw new NullPointerException(); + } + result.mapIndex_.set(index, value); + return this; + } + public Builder setMapIndex(int index, net.osmand.binary.OsmandIndex.MapPart.Builder builderForValue) { + result.mapIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addMapIndex(net.osmand.binary.OsmandIndex.MapPart value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + result.mapIndex_.add(value); + return this; + } + public Builder addMapIndex(net.osmand.binary.OsmandIndex.MapPart.Builder builderForValue) { + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + result.mapIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllMapIndex( + java.lang.Iterable values) { + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.mapIndex_); + return this; + } + public Builder clearMapIndex() { + result.mapIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .RoutingPart routingIndex = 12; + public java.util.List getRoutingIndexList() { + return java.util.Collections.unmodifiableList(result.routingIndex_); + } + public int getRoutingIndexCount() { + return result.getRoutingIndexCount(); + } + public net.osmand.binary.OsmandIndex.RoutingPart getRoutingIndex(int index) { + return result.getRoutingIndex(index); + } + public Builder setRoutingIndex(int index, net.osmand.binary.OsmandIndex.RoutingPart value) { + if (value == null) { + throw new NullPointerException(); + } + result.routingIndex_.set(index, value); + return this; + } + public Builder setRoutingIndex(int index, net.osmand.binary.OsmandIndex.RoutingPart.Builder builderForValue) { + result.routingIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addRoutingIndex(net.osmand.binary.OsmandIndex.RoutingPart value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + result.routingIndex_.add(value); + return this; + } + public Builder addRoutingIndex(net.osmand.binary.OsmandIndex.RoutingPart.Builder builderForValue) { + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + result.routingIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllRoutingIndex( + java.lang.Iterable values) { + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.routingIndex_); + return this; + } + public Builder clearRoutingIndex() { + result.routingIndex_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:FileIndex) + } + + static { + defaultInstance = new FileIndex(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:FileIndex) + } + + public static final class AddressPart extends + com.google.protobuf.GeneratedMessageLite { + // Use AddressPart.newBuilder() to construct. + private AddressPart() { + initFields(); + } + private AddressPart(boolean noInit) {} + + private static final AddressPart defaultInstance; + public static AddressPart getDefaultInstance() { + return defaultInstance; + } + + @Override + public AddressPart getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // optional string name = 3; + public static final int NAME_FIELD_NUMBER = 3; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string nameEn = 4; + public static final int NAMEEN_FIELD_NUMBER = 4; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // optional int32 indexNameOffset = 5; + public static final int INDEXNAMEOFFSET_FIELD_NUMBER = 5; + private boolean hasIndexNameOffset; + private int indexNameOffset_ = 0; + public boolean hasIndexNameOffset() { return hasIndexNameOffset; } + public int getIndexNameOffset() { return indexNameOffset_; } + + // repeated .CityBlock cities = 8; + public static final int CITIES_FIELD_NUMBER = 8; + private java.util.List cities_ = + java.util.Collections.emptyList(); + public java.util.List getCitiesList() { + return cities_; + } + public int getCitiesCount() { return cities_.size(); } + public net.osmand.binary.OsmandIndex.CityBlock getCities(int index) { + return cities_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + for (net.osmand.binary.OsmandIndex.CityBlock element : getCitiesList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasName()) { + output.writeString(3, getName()); + } + if (hasNameEn()) { + output.writeString(4, getNameEn()); + } + if (hasIndexNameOffset()) { + output.writeInt32(5, getIndexNameOffset()); + } + for (net.osmand.binary.OsmandIndex.CityBlock element : getCitiesList()) { + output.writeMessage(8, element); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(4, getNameEn()); + } + if (hasIndexNameOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, getIndexNameOffset()); + } + for (net.osmand.binary.OsmandIndex.CityBlock element : getCitiesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, element); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.AddressPart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.AddressPart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.AddressPart prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.AddressPart, Builder> { + private net.osmand.binary.OsmandIndex.AddressPart result; + + // Construct using net.osmand.binary.OsmandIndex.AddressPart.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.AddressPart(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.AddressPart internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.AddressPart(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.AddressPart getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.AddressPart.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.AddressPart build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.AddressPart buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.AddressPart buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.cities_ != java.util.Collections.EMPTY_LIST) { + result.cities_ = + java.util.Collections.unmodifiableList(result.cities_); + } + net.osmand.binary.OsmandIndex.AddressPart returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.AddressPart other) { + if (other == net.osmand.binary.OsmandIndex.AddressPart.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasIndexNameOffset()) { + setIndexNameOffset(other.getIndexNameOffset()); + } + if (!other.cities_.isEmpty()) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.addAll(other.cities_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 26: { + setName(input.readString()); + break; + } + case 34: { + setNameEn(input.readString()); + break; + } + case 40: { + setIndexNameOffset(input.readInt32()); + break; + } + case 66: { + net.osmand.binary.OsmandIndex.CityBlock.Builder subBuilder = net.osmand.binary.OsmandIndex.CityBlock.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addCities(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // optional string name = 3; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string nameEn = 4; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // optional int32 indexNameOffset = 5; + public boolean hasIndexNameOffset() { + return result.hasIndexNameOffset(); + } + public int getIndexNameOffset() { + return result.getIndexNameOffset(); + } + public Builder setIndexNameOffset(int value) { + result.hasIndexNameOffset = true; + result.indexNameOffset_ = value; + return this; + } + public Builder clearIndexNameOffset() { + result.hasIndexNameOffset = false; + result.indexNameOffset_ = 0; + return this; + } + + // repeated .CityBlock cities = 8; + public java.util.List getCitiesList() { + return java.util.Collections.unmodifiableList(result.cities_); + } + public int getCitiesCount() { + return result.getCitiesCount(); + } + public net.osmand.binary.OsmandIndex.CityBlock getCities(int index) { + return result.getCities(index); + } + public Builder setCities(int index, net.osmand.binary.OsmandIndex.CityBlock value) { + if (value == null) { + throw new NullPointerException(); + } + result.cities_.set(index, value); + return this; + } + public Builder setCities(int index, net.osmand.binary.OsmandIndex.CityBlock.Builder builderForValue) { + result.cities_.set(index, builderForValue.build()); + return this; + } + public Builder addCities(net.osmand.binary.OsmandIndex.CityBlock value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.add(value); + return this; + } + public Builder addCities(net.osmand.binary.OsmandIndex.CityBlock.Builder builderForValue) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.add(builderForValue.build()); + return this; + } + public Builder addAllCities( + java.lang.Iterable values) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + super.addAll(values, result.cities_); + return this; + } + public Builder clearCities() { + result.cities_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:AddressPart) + } + + static { + defaultInstance = new AddressPart(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:AddressPart) + } + + public static final class CityBlock extends + com.google.protobuf.GeneratedMessageLite { + // Use CityBlock.newBuilder() to construct. + private CityBlock() { + initFields(); + } + private CityBlock(boolean noInit) {} + + private static final CityBlock defaultInstance; + public static CityBlock getDefaultInstance() { + return defaultInstance; + } + + @Override + public CityBlock getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // required int32 type = 3; + public static final int TYPE_FIELD_NUMBER = 3; + private boolean hasType; + private int type_ = 0; + public boolean hasType() { return hasType; } + public int getType() { return type_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + if (!hasType) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasType()) { + output.writeInt32(3, getType()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasType()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, getType()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.CityBlock parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.CityBlock parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.CityBlock prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.CityBlock, Builder> { + private net.osmand.binary.OsmandIndex.CityBlock result; + + // Construct using net.osmand.binary.OsmandIndex.CityBlock.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.CityBlock(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.CityBlock internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.CityBlock(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.CityBlock getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.CityBlock.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.CityBlock build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.CityBlock buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.CityBlock buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandIndex.CityBlock returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.CityBlock other) { + if (other == net.osmand.binary.OsmandIndex.CityBlock.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasType()) { + setType(other.getType()); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 24: { + setType(input.readInt32()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // required int32 type = 3; + public boolean hasType() { + return result.hasType(); + } + public int getType() { + return result.getType(); + } + public Builder setType(int value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder clearType() { + result.hasType = false; + result.type_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:CityBlock) + } + + static { + defaultInstance = new CityBlock(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:CityBlock) + } + + public static final class PoiPart extends + com.google.protobuf.GeneratedMessageLite { + // Use PoiPart.newBuilder() to construct. + private PoiPart() { + initFields(); + } + private PoiPart(boolean noInit) {} + + private static final PoiPart defaultInstance; + public static PoiPart getDefaultInstance() { + return defaultInstance; + } + + @Override + public PoiPart getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // optional string name = 3; + public static final int NAME_FIELD_NUMBER = 3; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // required int32 left = 4; + public static final int LEFT_FIELD_NUMBER = 4; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required int32 right = 5; + public static final int RIGHT_FIELD_NUMBER = 5; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required int32 top = 6; + public static final int TOP_FIELD_NUMBER = 6; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required int32 bottom = 7; + public static final int BOTTOM_FIELD_NUMBER = 7; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasName()) { + output.writeString(3, getName()); + } + if (hasLeft()) { + output.writeInt32(4, getLeft()); + } + if (hasRight()) { + output.writeInt32(5, getRight()); + } + if (hasTop()) { + output.writeInt32(6, getTop()); + } + if (hasBottom()) { + output.writeInt32(7, getBottom()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getName()); + } + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(6, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(7, getBottom()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.PoiPart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.PoiPart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.PoiPart prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.PoiPart, Builder> { + private net.osmand.binary.OsmandIndex.PoiPart result; + + // Construct using net.osmand.binary.OsmandIndex.PoiPart.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.PoiPart(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.PoiPart internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.PoiPart(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.PoiPart getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.PoiPart.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.PoiPart build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.PoiPart buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.PoiPart buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandIndex.PoiPart returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.PoiPart other) { + if (other == net.osmand.binary.OsmandIndex.PoiPart.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 26: { + setName(input.readString()); + break; + } + case 32: { + setLeft(input.readInt32()); + break; + } + case 40: { + setRight(input.readInt32()); + break; + } + case 48: { + setTop(input.readInt32()); + break; + } + case 56: { + setBottom(input.readInt32()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // optional string name = 3; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // required int32 left = 4; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required int32 right = 5; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required int32 top = 6; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required int32 bottom = 7; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:PoiPart) + } + + static { + defaultInstance = new PoiPart(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:PoiPart) + } + + public static final class MapLevel extends + com.google.protobuf.GeneratedMessageLite { + // Use MapLevel.newBuilder() to construct. + private MapLevel() { + initFields(); + } + private MapLevel(boolean noInit) {} + + private static final MapLevel defaultInstance; + public static MapLevel getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapLevel getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // required int32 left = 4; + public static final int LEFT_FIELD_NUMBER = 4; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required int32 right = 5; + public static final int RIGHT_FIELD_NUMBER = 5; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required int32 top = 6; + public static final int TOP_FIELD_NUMBER = 6; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required int32 bottom = 7; + public static final int BOTTOM_FIELD_NUMBER = 7; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // optional int32 minzoom = 8; + public static final int MINZOOM_FIELD_NUMBER = 8; + private boolean hasMinzoom; + private int minzoom_ = 0; + public boolean hasMinzoom() { return hasMinzoom; } + public int getMinzoom() { return minzoom_; } + + // optional int32 maxzoom = 9; + public static final int MAXZOOM_FIELD_NUMBER = 9; + private boolean hasMaxzoom; + private int maxzoom_ = 0; + public boolean hasMaxzoom() { return hasMaxzoom; } + public int getMaxzoom() { return maxzoom_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasLeft()) { + output.writeInt32(4, getLeft()); + } + if (hasRight()) { + output.writeInt32(5, getRight()); + } + if (hasTop()) { + output.writeInt32(6, getTop()); + } + if (hasBottom()) { + output.writeInt32(7, getBottom()); + } + if (hasMinzoom()) { + output.writeInt32(8, getMinzoom()); + } + if (hasMaxzoom()) { + output.writeInt32(9, getMaxzoom()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(6, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(7, getBottom()); + } + if (hasMinzoom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(8, getMinzoom()); + } + if (hasMaxzoom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(9, getMaxzoom()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.MapLevel parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapLevel parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.MapLevel prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.MapLevel, Builder> { + private net.osmand.binary.OsmandIndex.MapLevel result; + + // Construct using net.osmand.binary.OsmandIndex.MapLevel.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.MapLevel(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.MapLevel internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.MapLevel(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.MapLevel getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.MapLevel.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.MapLevel build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.MapLevel buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.MapLevel buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandIndex.MapLevel returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.MapLevel other) { + if (other == net.osmand.binary.OsmandIndex.MapLevel.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (other.hasMinzoom()) { + setMinzoom(other.getMinzoom()); + } + if (other.hasMaxzoom()) { + setMaxzoom(other.getMaxzoom()); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 32: { + setLeft(input.readInt32()); + break; + } + case 40: { + setRight(input.readInt32()); + break; + } + case 48: { + setTop(input.readInt32()); + break; + } + case 56: { + setBottom(input.readInt32()); + break; + } + case 64: { + setMinzoom(input.readInt32()); + break; + } + case 72: { + setMaxzoom(input.readInt32()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // required int32 left = 4; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required int32 right = 5; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required int32 top = 6; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required int32 bottom = 7; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // optional int32 minzoom = 8; + public boolean hasMinzoom() { + return result.hasMinzoom(); + } + public int getMinzoom() { + return result.getMinzoom(); + } + public Builder setMinzoom(int value) { + result.hasMinzoom = true; + result.minzoom_ = value; + return this; + } + public Builder clearMinzoom() { + result.hasMinzoom = false; + result.minzoom_ = 0; + return this; + } + + // optional int32 maxzoom = 9; + public boolean hasMaxzoom() { + return result.hasMaxzoom(); + } + public int getMaxzoom() { + return result.getMaxzoom(); + } + public Builder setMaxzoom(int value) { + result.hasMaxzoom = true; + result.maxzoom_ = value; + return this; + } + public Builder clearMaxzoom() { + result.hasMaxzoom = false; + result.maxzoom_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:MapLevel) + } + + static { + defaultInstance = new MapLevel(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:MapLevel) + } + + public static final class MapPart extends + com.google.protobuf.GeneratedMessageLite { + // Use MapPart.newBuilder() to construct. + private MapPart() { + initFields(); + } + private MapPart(boolean noInit) {} + + private static final MapPart defaultInstance; + public static MapPart getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapPart getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // optional string name = 3; + public static final int NAME_FIELD_NUMBER = 3; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // repeated .MapLevel levels = 5; + public static final int LEVELS_FIELD_NUMBER = 5; + private java.util.List levels_ = + java.util.Collections.emptyList(); + public java.util.List getLevelsList() { + return levels_; + } + public int getLevelsCount() { return levels_.size(); } + public net.osmand.binary.OsmandIndex.MapLevel getLevels(int index) { + return levels_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + for (net.osmand.binary.OsmandIndex.MapLevel element : getLevelsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasName()) { + output.writeString(3, getName()); + } + for (net.osmand.binary.OsmandIndex.MapLevel element : getLevelsList()) { + output.writeMessage(5, element); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getName()); + } + for (net.osmand.binary.OsmandIndex.MapLevel element : getLevelsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.MapPart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.MapPart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.MapPart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.MapPart prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.MapPart, Builder> { + private net.osmand.binary.OsmandIndex.MapPart result; + + // Construct using net.osmand.binary.OsmandIndex.MapPart.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.MapPart(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.MapPart internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.MapPart(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.MapPart getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.MapPart.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.MapPart build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.MapPart buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.MapPart buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.levels_ != java.util.Collections.EMPTY_LIST) { + result.levels_ = + java.util.Collections.unmodifiableList(result.levels_); + } + net.osmand.binary.OsmandIndex.MapPart returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.MapPart other) { + if (other == net.osmand.binary.OsmandIndex.MapPart.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (!other.levels_.isEmpty()) { + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + result.levels_.addAll(other.levels_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 26: { + setName(input.readString()); + break; + } + case 42: { + net.osmand.binary.OsmandIndex.MapLevel.Builder subBuilder = net.osmand.binary.OsmandIndex.MapLevel.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addLevels(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // optional string name = 3; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // repeated .MapLevel levels = 5; + public java.util.List getLevelsList() { + return java.util.Collections.unmodifiableList(result.levels_); + } + public int getLevelsCount() { + return result.getLevelsCount(); + } + public net.osmand.binary.OsmandIndex.MapLevel getLevels(int index) { + return result.getLevels(index); + } + public Builder setLevels(int index, net.osmand.binary.OsmandIndex.MapLevel value) { + if (value == null) { + throw new NullPointerException(); + } + result.levels_.set(index, value); + return this; + } + public Builder setLevels(int index, net.osmand.binary.OsmandIndex.MapLevel.Builder builderForValue) { + result.levels_.set(index, builderForValue.build()); + return this; + } + public Builder addLevels(net.osmand.binary.OsmandIndex.MapLevel value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + result.levels_.add(value); + return this; + } + public Builder addLevels(net.osmand.binary.OsmandIndex.MapLevel.Builder builderForValue) { + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + result.levels_.add(builderForValue.build()); + return this; + } + public Builder addAllLevels( + java.lang.Iterable values) { + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + super.addAll(values, result.levels_); + return this; + } + public Builder clearLevels() { + result.levels_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:MapPart) + } + + static { + defaultInstance = new MapPart(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:MapPart) + } + + public static final class RoutingSubregion extends + com.google.protobuf.GeneratedMessageLite { + // Use RoutingSubregion.newBuilder() to construct. + private RoutingSubregion() { + initFields(); + } + private RoutingSubregion(boolean noInit) {} + + private static final RoutingSubregion defaultInstance; + public static RoutingSubregion getDefaultInstance() { + return defaultInstance; + } + + @Override + public RoutingSubregion getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // optional bool basemap = 3; + public static final int BASEMAP_FIELD_NUMBER = 3; + private boolean hasBasemap; + private boolean basemap_ = false; + public boolean hasBasemap() { return hasBasemap; } + public boolean getBasemap() { return basemap_; } + + // required int32 left = 4; + public static final int LEFT_FIELD_NUMBER = 4; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required int32 right = 5; + public static final int RIGHT_FIELD_NUMBER = 5; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required int32 top = 6; + public static final int TOP_FIELD_NUMBER = 6; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required int32 bottom = 7; + public static final int BOTTOM_FIELD_NUMBER = 7; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // required uint32 shifToData = 8; + public static final int SHIFTODATA_FIELD_NUMBER = 8; + private boolean hasShifToData; + private int shifToData_ = 0; + public boolean hasShifToData() { return hasShifToData; } + public int getShifToData() { return shifToData_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + if (!hasShifToData) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasBasemap()) { + output.writeBool(3, getBasemap()); + } + if (hasLeft()) { + output.writeInt32(4, getLeft()); + } + if (hasRight()) { + output.writeInt32(5, getRight()); + } + if (hasTop()) { + output.writeInt32(6, getTop()); + } + if (hasBottom()) { + output.writeInt32(7, getBottom()); + } + if (hasShifToData()) { + output.writeUInt32(8, getShifToData()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasBasemap()) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(3, getBasemap()); + } + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(6, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(7, getBottom()); + } + if (hasShifToData()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(8, getShifToData()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingSubregion parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.RoutingSubregion prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.RoutingSubregion, Builder> { + private net.osmand.binary.OsmandIndex.RoutingSubregion result; + + // Construct using net.osmand.binary.OsmandIndex.RoutingSubregion.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.RoutingSubregion(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.RoutingSubregion internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.RoutingSubregion(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.RoutingSubregion getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.RoutingSubregion.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.RoutingSubregion build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.RoutingSubregion buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.RoutingSubregion buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandIndex.RoutingSubregion returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.RoutingSubregion other) { + if (other == net.osmand.binary.OsmandIndex.RoutingSubregion.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasBasemap()) { + setBasemap(other.getBasemap()); + } + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (other.hasShifToData()) { + setShifToData(other.getShifToData()); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 24: { + setBasemap(input.readBool()); + break; + } + case 32: { + setLeft(input.readInt32()); + break; + } + case 40: { + setRight(input.readInt32()); + break; + } + case 48: { + setTop(input.readInt32()); + break; + } + case 56: { + setBottom(input.readInt32()); + break; + } + case 64: { + setShifToData(input.readUInt32()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // optional bool basemap = 3; + public boolean hasBasemap() { + return result.hasBasemap(); + } + public boolean getBasemap() { + return result.getBasemap(); + } + public Builder setBasemap(boolean value) { + result.hasBasemap = true; + result.basemap_ = value; + return this; + } + public Builder clearBasemap() { + result.hasBasemap = false; + result.basemap_ = false; + return this; + } + + // required int32 left = 4; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required int32 right = 5; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required int32 top = 6; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required int32 bottom = 7; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // required uint32 shifToData = 8; + public boolean hasShifToData() { + return result.hasShifToData(); + } + public int getShifToData() { + return result.getShifToData(); + } + public Builder setShifToData(int value) { + result.hasShifToData = true; + result.shifToData_ = value; + return this; + } + public Builder clearShifToData() { + result.hasShifToData = false; + result.shifToData_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:RoutingSubregion) + } + + static { + defaultInstance = new RoutingSubregion(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:RoutingSubregion) + } + + public static final class RoutingPart extends + com.google.protobuf.GeneratedMessageLite { + // Use RoutingPart.newBuilder() to construct. + private RoutingPart() { + initFields(); + } + private RoutingPart(boolean noInit) {} + + private static final RoutingPart defaultInstance; + public static RoutingPart getDefaultInstance() { + return defaultInstance; + } + + @Override + public RoutingPart getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // optional string name = 3; + public static final int NAME_FIELD_NUMBER = 3; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // repeated .RoutingSubregion subregions = 5; + public static final int SUBREGIONS_FIELD_NUMBER = 5; + private java.util.List subregions_ = + java.util.Collections.emptyList(); + public java.util.List getSubregionsList() { + return subregions_; + } + public int getSubregionsCount() { return subregions_.size(); } + public net.osmand.binary.OsmandIndex.RoutingSubregion getSubregions(int index) { + return subregions_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + for (net.osmand.binary.OsmandIndex.RoutingSubregion element : getSubregionsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasName()) { + output.writeString(3, getName()); + } + for (net.osmand.binary.OsmandIndex.RoutingSubregion element : getSubregionsList()) { + output.writeMessage(5, element); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getName()); + } + for (net.osmand.binary.OsmandIndex.RoutingSubregion element : getSubregionsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.RoutingPart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.RoutingPart prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.RoutingPart, Builder> { + private net.osmand.binary.OsmandIndex.RoutingPart result; + + // Construct using net.osmand.binary.OsmandIndex.RoutingPart.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.RoutingPart(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.RoutingPart internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.RoutingPart(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.RoutingPart getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.RoutingPart.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.RoutingPart build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.RoutingPart buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.RoutingPart buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.subregions_ != java.util.Collections.EMPTY_LIST) { + result.subregions_ = + java.util.Collections.unmodifiableList(result.subregions_); + } + net.osmand.binary.OsmandIndex.RoutingPart returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.RoutingPart other) { + if (other == net.osmand.binary.OsmandIndex.RoutingPart.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (!other.subregions_.isEmpty()) { + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + result.subregions_.addAll(other.subregions_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 26: { + setName(input.readString()); + break; + } + case 42: { + net.osmand.binary.OsmandIndex.RoutingSubregion.Builder subBuilder = net.osmand.binary.OsmandIndex.RoutingSubregion.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addSubregions(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // optional string name = 3; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // repeated .RoutingSubregion subregions = 5; + public java.util.List getSubregionsList() { + return java.util.Collections.unmodifiableList(result.subregions_); + } + public int getSubregionsCount() { + return result.getSubregionsCount(); + } + public net.osmand.binary.OsmandIndex.RoutingSubregion getSubregions(int index) { + return result.getSubregions(index); + } + public Builder setSubregions(int index, net.osmand.binary.OsmandIndex.RoutingSubregion value) { + if (value == null) { + throw new NullPointerException(); + } + result.subregions_.set(index, value); + return this; + } + public Builder setSubregions(int index, net.osmand.binary.OsmandIndex.RoutingSubregion.Builder builderForValue) { + result.subregions_.set(index, builderForValue.build()); + return this; + } + public Builder addSubregions(net.osmand.binary.OsmandIndex.RoutingSubregion value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + result.subregions_.add(value); + return this; + } + public Builder addSubregions(net.osmand.binary.OsmandIndex.RoutingSubregion.Builder builderForValue) { + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + result.subregions_.add(builderForValue.build()); + return this; + } + public Builder addAllSubregions( + java.lang.Iterable values) { + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + super.addAll(values, result.subregions_); + return this; + } + public Builder clearSubregions() { + result.subregions_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:RoutingPart) + } + + static { + defaultInstance = new RoutingPart(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:RoutingPart) + } + + public static final class TransportPart extends + com.google.protobuf.GeneratedMessageLite { + // Use TransportPart.newBuilder() to construct. + private TransportPart() { + initFields(); + } + private TransportPart(boolean noInit) {} + + private static final TransportPart defaultInstance; + public static TransportPart getDefaultInstance() { + return defaultInstance; + } + + @Override + public TransportPart getDefaultInstanceForType() { + return defaultInstance; + } + + // required int64 size = 1; + public static final int SIZE_FIELD_NUMBER = 1; + private boolean hasSize; + private long size_ = 0L; + public boolean hasSize() { return hasSize; } + public long getSize() { return size_; } + + // required int64 offset = 2; + public static final int OFFSET_FIELD_NUMBER = 2; + private boolean hasOffset; + private long offset_ = 0L; + public boolean hasOffset() { return hasOffset; } + public long getOffset() { return offset_; } + + // optional string name = 3; + public static final int NAME_FIELD_NUMBER = 3; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional int32 left = 4; + public static final int LEFT_FIELD_NUMBER = 4; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // optional int32 right = 5; + public static final int RIGHT_FIELD_NUMBER = 5; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // optional int32 top = 6; + public static final int TOP_FIELD_NUMBER = 6; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // optional int32 bottom = 7; + public static final int BOTTOM_FIELD_NUMBER = 7; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // optional uint32 stringTableOffset = 8; + public static final int STRINGTABLEOFFSET_FIELD_NUMBER = 8; + private boolean hasStringTableOffset; + private int stringTableOffset_ = 0; + public boolean hasStringTableOffset() { return hasStringTableOffset; } + public int getStringTableOffset() { return stringTableOffset_; } + + // optional uint32 stringTableLength = 9; + public static final int STRINGTABLELENGTH_FIELD_NUMBER = 9; + private boolean hasStringTableLength; + private int stringTableLength_ = 0; + public boolean hasStringTableLength() { return hasStringTableLength; } + public int getStringTableLength() { return stringTableLength_; } + + // optional uint32 stopsTableOffset = 10; + public static final int STOPSTABLEOFFSET_FIELD_NUMBER = 10; + private boolean hasStopsTableOffset; + private int stopsTableOffset_ = 0; + public boolean hasStopsTableOffset() { return hasStopsTableOffset; } + public int getStopsTableOffset() { return stopsTableOffset_; } + + // optional uint32 stopsTableLength = 11; + public static final int STOPSTABLELENGTH_FIELD_NUMBER = 11; + private boolean hasStopsTableLength; + private int stopsTableLength_ = 0; + public boolean hasStopsTableLength() { return hasStopsTableLength; } + public int getStopsTableLength() { return stopsTableLength_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasSize) return false; + if (!hasOffset) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasSize()) { + output.writeInt64(1, getSize()); + } + if (hasOffset()) { + output.writeInt64(2, getOffset()); + } + if (hasName()) { + output.writeString(3, getName()); + } + if (hasLeft()) { + output.writeInt32(4, getLeft()); + } + if (hasRight()) { + output.writeInt32(5, getRight()); + } + if (hasTop()) { + output.writeInt32(6, getTop()); + } + if (hasBottom()) { + output.writeInt32(7, getBottom()); + } + if (hasStringTableOffset()) { + output.writeUInt32(8, getStringTableOffset()); + } + if (hasStringTableLength()) { + output.writeUInt32(9, getStringTableLength()); + } + if (hasStopsTableOffset()) { + output.writeUInt32(10, getStopsTableOffset()); + } + if (hasStopsTableLength()) { + output.writeUInt32(11, getStopsTableLength()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasSize()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, getSize()); + } + if (hasOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, getOffset()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getName()); + } + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(6, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(7, getBottom()); + } + if (hasStringTableOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(8, getStringTableOffset()); + } + if (hasStringTableLength()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(9, getStringTableLength()); + } + if (hasStopsTableOffset()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(10, getStopsTableOffset()); + } + if (hasStopsTableLength()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(11, getStopsTableLength()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.TransportPart parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandIndex.TransportPart parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandIndex.TransportPart prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.binary.OsmandIndex.TransportPart, Builder> { + private net.osmand.binary.OsmandIndex.TransportPart result; + + // Construct using net.osmand.binary.OsmandIndex.TransportPart.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandIndex.TransportPart(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandIndex.TransportPart internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandIndex.TransportPart(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.binary.OsmandIndex.TransportPart getDefaultInstanceForType() { + return net.osmand.binary.OsmandIndex.TransportPart.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandIndex.TransportPart build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandIndex.TransportPart buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandIndex.TransportPart buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandIndex.TransportPart returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.binary.OsmandIndex.TransportPart other) { + if (other == net.osmand.binary.OsmandIndex.TransportPart.getDefaultInstance()) return this; + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasOffset()) { + setOffset(other.getOffset()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (other.hasStringTableOffset()) { + setStringTableOffset(other.getStringTableOffset()); + } + if (other.hasStringTableLength()) { + setStringTableLength(other.getStringTableLength()); + } + if (other.hasStopsTableOffset()) { + setStopsTableOffset(other.getStopsTableOffset()); + } + if (other.hasStopsTableLength()) { + setStopsTableLength(other.getStopsTableLength()); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setSize(input.readInt64()); + break; + } + case 16: { + setOffset(input.readInt64()); + break; + } + case 26: { + setName(input.readString()); + break; + } + case 32: { + setLeft(input.readInt32()); + break; + } + case 40: { + setRight(input.readInt32()); + break; + } + case 48: { + setTop(input.readInt32()); + break; + } + case 56: { + setBottom(input.readInt32()); + break; + } + case 64: { + setStringTableOffset(input.readUInt32()); + break; + } + case 72: { + setStringTableLength(input.readUInt32()); + break; + } + case 80: { + setStopsTableOffset(input.readUInt32()); + break; + } + case 88: { + setStopsTableLength(input.readUInt32()); + break; + } + } + } + } + + + // required int64 size = 1; + public boolean hasSize() { + return result.hasSize(); + } + public long getSize() { + return result.getSize(); + } + public Builder setSize(long value) { + result.hasSize = true; + result.size_ = value; + return this; + } + public Builder clearSize() { + result.hasSize = false; + result.size_ = 0L; + return this; + } + + // required int64 offset = 2; + public boolean hasOffset() { + return result.hasOffset(); + } + public long getOffset() { + return result.getOffset(); + } + public Builder setOffset(long value) { + result.hasOffset = true; + result.offset_ = value; + return this; + } + public Builder clearOffset() { + result.hasOffset = false; + result.offset_ = 0L; + return this; + } + + // optional string name = 3; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional int32 left = 4; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // optional int32 right = 5; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // optional int32 top = 6; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // optional int32 bottom = 7; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // optional uint32 stringTableOffset = 8; + public boolean hasStringTableOffset() { + return result.hasStringTableOffset(); + } + public int getStringTableOffset() { + return result.getStringTableOffset(); + } + public Builder setStringTableOffset(int value) { + result.hasStringTableOffset = true; + result.stringTableOffset_ = value; + return this; + } + public Builder clearStringTableOffset() { + result.hasStringTableOffset = false; + result.stringTableOffset_ = 0; + return this; + } + + // optional uint32 stringTableLength = 9; + public boolean hasStringTableLength() { + return result.hasStringTableLength(); + } + public int getStringTableLength() { + return result.getStringTableLength(); + } + public Builder setStringTableLength(int value) { + result.hasStringTableLength = true; + result.stringTableLength_ = value; + return this; + } + public Builder clearStringTableLength() { + result.hasStringTableLength = false; + result.stringTableLength_ = 0; + return this; + } + + // optional uint32 stopsTableOffset = 10; + public boolean hasStopsTableOffset() { + return result.hasStopsTableOffset(); + } + public int getStopsTableOffset() { + return result.getStopsTableOffset(); + } + public Builder setStopsTableOffset(int value) { + result.hasStopsTableOffset = true; + result.stopsTableOffset_ = value; + return this; + } + public Builder clearStopsTableOffset() { + result.hasStopsTableOffset = false; + result.stopsTableOffset_ = 0; + return this; + } + + // optional uint32 stopsTableLength = 11; + public boolean hasStopsTableLength() { + return result.hasStopsTableLength(); + } + public int getStopsTableLength() { + return result.getStopsTableLength(); + } + public Builder setStopsTableLength(int value) { + result.hasStopsTableLength = true; + result.stopsTableLength_ = value; + return this; + } + public Builder clearStopsTableLength() { + result.hasStopsTableLength = false; + result.stopsTableLength_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:TransportPart) + } + + static { + defaultInstance = new TransportPart(true); + net.osmand.binary.OsmandIndex.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TransportPart) + } + + + static { + } + + public static void internalForceInit() {} + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/OsmAnd-java/src/net/osmand/binary/OsmandOdb.java b/OsmAnd-java/src/net/osmand/binary/OsmandOdb.java new file mode 100644 index 0000000000..1b20c77ce9 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/OsmandOdb.java @@ -0,0 +1,24438 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: DataExtractionOSM/src/osmand_odb.proto + +package net.osmand.binary; + +public final class OsmandOdb { + private OsmandOdb() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + public static final class OsmAndStructure extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndStructure.newBuilder() to construct. + private OsmAndStructure() { + initFields(); + } + private OsmAndStructure(boolean noInit) {} + + private static final OsmAndStructure defaultInstance; + public static OsmAndStructure getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndStructure getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndStructure_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndStructure_fieldAccessorTable; + } + + // required uint32 version = 1; + public static final int VERSION_FIELD_NUMBER = 1; + private boolean hasVersion; + private int version_ = 0; + public boolean hasVersion() { return hasVersion; } + public int getVersion() { return version_; } + + // required int64 dateCreated = 18; + public static final int DATECREATED_FIELD_NUMBER = 18; + private boolean hasDateCreated; + private long dateCreated_ = 0L; + public boolean hasDateCreated() { return hasDateCreated; } + public long getDateCreated() { return dateCreated_; } + + // repeated .OsmAndAddressIndex addressIndex = 7; + public static final int ADDRESSINDEX_FIELD_NUMBER = 7; + private java.util.List addressIndex_ = + java.util.Collections.emptyList(); + public java.util.List getAddressIndexList() { + return addressIndex_; + } + public int getAddressIndexCount() { return addressIndex_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex getAddressIndex(int index) { + return addressIndex_.get(index); + } + + // repeated .OsmAndTransportIndex transportIndex = 4; + public static final int TRANSPORTINDEX_FIELD_NUMBER = 4; + private java.util.List transportIndex_ = + java.util.Collections.emptyList(); + public java.util.List getTransportIndexList() { + return transportIndex_; + } + public int getTransportIndexCount() { return transportIndex_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndTransportIndex getTransportIndex(int index) { + return transportIndex_.get(index); + } + + // repeated .OsmAndPoiIndex poiIndex = 8; + public static final int POIINDEX_FIELD_NUMBER = 8; + private java.util.List poiIndex_ = + java.util.Collections.emptyList(); + public java.util.List getPoiIndexList() { + return poiIndex_; + } + public int getPoiIndexCount() { return poiIndex_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiIndex getPoiIndex(int index) { + return poiIndex_.get(index); + } + + // repeated .OsmAndMapIndex mapIndex = 6; + public static final int MAPINDEX_FIELD_NUMBER = 6; + private java.util.List mapIndex_ = + java.util.Collections.emptyList(); + public java.util.List getMapIndexList() { + return mapIndex_; + } + public int getMapIndexCount() { return mapIndex_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex getMapIndex(int index) { + return mapIndex_.get(index); + } + + // repeated .OsmAndRoutingIndex routingIndex = 9; + public static final int ROUTINGINDEX_FIELD_NUMBER = 9; + private java.util.List routingIndex_ = + java.util.Collections.emptyList(); + public java.util.List getRoutingIndexList() { + return routingIndex_; + } + public int getRoutingIndexCount() { return routingIndex_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex getRoutingIndex(int index) { + return routingIndex_.get(index); + } + + // required uint32 versionConfirm = 32; + public static final int VERSIONCONFIRM_FIELD_NUMBER = 32; + private boolean hasVersionConfirm; + private int versionConfirm_ = 0; + public boolean hasVersionConfirm() { return hasVersionConfirm; } + public int getVersionConfirm() { return versionConfirm_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasVersion) return false; + if (!hasDateCreated) return false; + if (!hasVersionConfirm) return false; + for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex element : getAddressIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndTransportIndex element : getTransportIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiIndex element : getPoiIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex element : getMapIndexList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex element : getRoutingIndexList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasVersion()) { + output.writeUInt32(1, getVersion()); + } + for (net.osmand.binary.OsmandOdb.OsmAndTransportIndex element : getTransportIndexList()) { + output.writeMessage(4, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex element : getMapIndexList()) { + output.writeMessage(6, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex element : getAddressIndexList()) { + output.writeMessage(7, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiIndex element : getPoiIndexList()) { + output.writeMessage(8, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex element : getRoutingIndexList()) { + output.writeMessage(9, element); + } + if (hasDateCreated()) { + output.writeInt64(18, getDateCreated()); + } + if (hasVersionConfirm()) { + output.writeUInt32(32, getVersionConfirm()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasVersion()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, getVersion()); + } + for (net.osmand.binary.OsmandOdb.OsmAndTransportIndex element : getTransportIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex element : getMapIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex element : getAddressIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiIndex element : getPoiIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex element : getRoutingIndexList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, element); + } + if (hasDateCreated()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(18, getDateCreated()); + } + if (hasVersionConfirm()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(32, getVersionConfirm()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndStructure parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndStructure prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndStructure result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndStructure.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndStructure(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndStructure internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndStructure(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndStructure.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndStructure getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndStructure.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndStructure build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndStructure buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndStructure buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.addressIndex_ != java.util.Collections.EMPTY_LIST) { + result.addressIndex_ = + java.util.Collections.unmodifiableList(result.addressIndex_); + } + if (result.transportIndex_ != java.util.Collections.EMPTY_LIST) { + result.transportIndex_ = + java.util.Collections.unmodifiableList(result.transportIndex_); + } + if (result.poiIndex_ != java.util.Collections.EMPTY_LIST) { + result.poiIndex_ = + java.util.Collections.unmodifiableList(result.poiIndex_); + } + if (result.mapIndex_ != java.util.Collections.EMPTY_LIST) { + result.mapIndex_ = + java.util.Collections.unmodifiableList(result.mapIndex_); + } + if (result.routingIndex_ != java.util.Collections.EMPTY_LIST) { + result.routingIndex_ = + java.util.Collections.unmodifiableList(result.routingIndex_); + } + net.osmand.binary.OsmandOdb.OsmAndStructure returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndStructure) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndStructure)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndStructure other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndStructure.getDefaultInstance()) return this; + if (other.hasVersion()) { + setVersion(other.getVersion()); + } + if (other.hasDateCreated()) { + setDateCreated(other.getDateCreated()); + } + if (!other.addressIndex_.isEmpty()) { + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + result.addressIndex_.addAll(other.addressIndex_); + } + if (!other.transportIndex_.isEmpty()) { + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + result.transportIndex_.addAll(other.transportIndex_); + } + if (!other.poiIndex_.isEmpty()) { + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + result.poiIndex_.addAll(other.poiIndex_); + } + if (!other.mapIndex_.isEmpty()) { + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + result.mapIndex_.addAll(other.mapIndex_); + } + if (!other.routingIndex_.isEmpty()) { + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + result.routingIndex_.addAll(other.routingIndex_); + } + if (other.hasVersionConfirm()) { + setVersionConfirm(other.getVersionConfirm()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setVersion(input.readUInt32()); + break; + } + case 34: { + net.osmand.binary.OsmandOdb.OsmAndTransportIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndTransportIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addTransportIndex(subBuilder.buildPartial()); + break; + } + case 50: { + net.osmand.binary.OsmandOdb.OsmAndMapIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndMapIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addMapIndex(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndAddressIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addAddressIndex(subBuilder.buildPartial()); + break; + } + case 66: { + net.osmand.binary.OsmandOdb.OsmAndPoiIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPoiIndex(subBuilder.buildPartial()); + break; + } + case 74: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRoutingIndex(subBuilder.buildPartial()); + break; + } + case 144: { + setDateCreated(input.readInt64()); + break; + } + case 256: { + setVersionConfirm(input.readUInt32()); + break; + } + } + } + } + + + // required uint32 version = 1; + public boolean hasVersion() { + return result.hasVersion(); + } + public int getVersion() { + return result.getVersion(); + } + public Builder setVersion(int value) { + result.hasVersion = true; + result.version_ = value; + return this; + } + public Builder clearVersion() { + result.hasVersion = false; + result.version_ = 0; + return this; + } + + // required int64 dateCreated = 18; + public boolean hasDateCreated() { + return result.hasDateCreated(); + } + public long getDateCreated() { + return result.getDateCreated(); + } + public Builder setDateCreated(long value) { + result.hasDateCreated = true; + result.dateCreated_ = value; + return this; + } + public Builder clearDateCreated() { + result.hasDateCreated = false; + result.dateCreated_ = 0L; + return this; + } + + // repeated .OsmAndAddressIndex addressIndex = 7; + public java.util.List getAddressIndexList() { + return java.util.Collections.unmodifiableList(result.addressIndex_); + } + public int getAddressIndexCount() { + return result.getAddressIndexCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex getAddressIndex(int index) { + return result.getAddressIndex(index); + } + public Builder setAddressIndex(int index, net.osmand.binary.OsmandOdb.OsmAndAddressIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.addressIndex_.set(index, value); + return this; + } + public Builder setAddressIndex(int index, net.osmand.binary.OsmandOdb.OsmAndAddressIndex.Builder builderForValue) { + result.addressIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addAddressIndex(net.osmand.binary.OsmandOdb.OsmAndAddressIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + result.addressIndex_.add(value); + return this; + } + public Builder addAddressIndex(net.osmand.binary.OsmandOdb.OsmAndAddressIndex.Builder builderForValue) { + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + result.addressIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllAddressIndex( + java.lang.Iterable values) { + if (result.addressIndex_.isEmpty()) { + result.addressIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.addressIndex_); + return this; + } + public Builder clearAddressIndex() { + result.addressIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndTransportIndex transportIndex = 4; + public java.util.List getTransportIndexList() { + return java.util.Collections.unmodifiableList(result.transportIndex_); + } + public int getTransportIndexCount() { + return result.getTransportIndexCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndTransportIndex getTransportIndex(int index) { + return result.getTransportIndex(index); + } + public Builder setTransportIndex(int index, net.osmand.binary.OsmandOdb.OsmAndTransportIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.transportIndex_.set(index, value); + return this; + } + public Builder setTransportIndex(int index, net.osmand.binary.OsmandOdb.OsmAndTransportIndex.Builder builderForValue) { + result.transportIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addTransportIndex(net.osmand.binary.OsmandOdb.OsmAndTransportIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + result.transportIndex_.add(value); + return this; + } + public Builder addTransportIndex(net.osmand.binary.OsmandOdb.OsmAndTransportIndex.Builder builderForValue) { + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + result.transportIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllTransportIndex( + java.lang.Iterable values) { + if (result.transportIndex_.isEmpty()) { + result.transportIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.transportIndex_); + return this; + } + public Builder clearTransportIndex() { + result.transportIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndPoiIndex poiIndex = 8; + public java.util.List getPoiIndexList() { + return java.util.Collections.unmodifiableList(result.poiIndex_); + } + public int getPoiIndexCount() { + return result.getPoiIndexCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiIndex getPoiIndex(int index) { + return result.getPoiIndex(index); + } + public Builder setPoiIndex(int index, net.osmand.binary.OsmandOdb.OsmAndPoiIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.poiIndex_.set(index, value); + return this; + } + public Builder setPoiIndex(int index, net.osmand.binary.OsmandOdb.OsmAndPoiIndex.Builder builderForValue) { + result.poiIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addPoiIndex(net.osmand.binary.OsmandOdb.OsmAndPoiIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + result.poiIndex_.add(value); + return this; + } + public Builder addPoiIndex(net.osmand.binary.OsmandOdb.OsmAndPoiIndex.Builder builderForValue) { + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + result.poiIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllPoiIndex( + java.lang.Iterable values) { + if (result.poiIndex_.isEmpty()) { + result.poiIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.poiIndex_); + return this; + } + public Builder clearPoiIndex() { + result.poiIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndMapIndex mapIndex = 6; + public java.util.List getMapIndexList() { + return java.util.Collections.unmodifiableList(result.mapIndex_); + } + public int getMapIndexCount() { + return result.getMapIndexCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex getMapIndex(int index) { + return result.getMapIndex(index); + } + public Builder setMapIndex(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.mapIndex_.set(index, value); + return this; + } + public Builder setMapIndex(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.Builder builderForValue) { + result.mapIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addMapIndex(net.osmand.binary.OsmandOdb.OsmAndMapIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + result.mapIndex_.add(value); + return this; + } + public Builder addMapIndex(net.osmand.binary.OsmandOdb.OsmAndMapIndex.Builder builderForValue) { + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + result.mapIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllMapIndex( + java.lang.Iterable values) { + if (result.mapIndex_.isEmpty()) { + result.mapIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.mapIndex_); + return this; + } + public Builder clearMapIndex() { + result.mapIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndRoutingIndex routingIndex = 9; + public java.util.List getRoutingIndexList() { + return java.util.Collections.unmodifiableList(result.routingIndex_); + } + public int getRoutingIndexCount() { + return result.getRoutingIndexCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex getRoutingIndex(int index) { + return result.getRoutingIndex(index); + } + public Builder setRoutingIndex(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.routingIndex_.set(index, value); + return this; + } + public Builder setRoutingIndex(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.Builder builderForValue) { + result.routingIndex_.set(index, builderForValue.build()); + return this; + } + public Builder addRoutingIndex(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + result.routingIndex_.add(value); + return this; + } + public Builder addRoutingIndex(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.Builder builderForValue) { + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + result.routingIndex_.add(builderForValue.build()); + return this; + } + public Builder addAllRoutingIndex( + java.lang.Iterable values) { + if (result.routingIndex_.isEmpty()) { + result.routingIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.routingIndex_); + return this; + } + public Builder clearRoutingIndex() { + result.routingIndex_ = java.util.Collections.emptyList(); + return this; + } + + // required uint32 versionConfirm = 32; + public boolean hasVersionConfirm() { + return result.hasVersionConfirm(); + } + public int getVersionConfirm() { + return result.getVersionConfirm(); + } + public Builder setVersionConfirm(int value) { + result.hasVersionConfirm = true; + result.versionConfirm_ = value; + return this; + } + public Builder clearVersionConfirm() { + result.hasVersionConfirm = false; + result.versionConfirm_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndStructure) + } + + static { + defaultInstance = new OsmAndStructure(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndStructure) + } + + public static final class OsmAndTileBox extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndTileBox.newBuilder() to construct. + private OsmAndTileBox() { + initFields(); + } + private OsmAndTileBox(boolean noInit) {} + + private static final OsmAndTileBox defaultInstance; + public static OsmAndTileBox getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndTileBox getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndTileBox_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndTileBox_fieldAccessorTable; + } + + // required uint32 left = 1; + public static final int LEFT_FIELD_NUMBER = 1; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required uint32 right = 2; + public static final int RIGHT_FIELD_NUMBER = 2; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required uint32 top = 3; + public static final int TOP_FIELD_NUMBER = 3; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required uint32 bottom = 4; + public static final int BOTTOM_FIELD_NUMBER = 4; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasLeft()) { + output.writeUInt32(1, getLeft()); + } + if (hasRight()) { + output.writeUInt32(2, getRight()); + } + if (hasTop()) { + output.writeUInt32(3, getTop()); + } + if (hasBottom()) { + output.writeUInt32(4, getBottom()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(2, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(3, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(4, getBottom()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTileBox parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndTileBox prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndTileBox result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndTileBox(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndTileBox internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndTileBox(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndTileBox.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndTileBox getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndTileBox build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndTileBox buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndTileBox buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndTileBox returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndTileBox) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndTileBox)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndTileBox other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance()) return this; + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setLeft(input.readUInt32()); + break; + } + case 16: { + setRight(input.readUInt32()); + break; + } + case 24: { + setTop(input.readUInt32()); + break; + } + case 32: { + setBottom(input.readUInt32()); + break; + } + } + } + } + + + // required uint32 left = 1; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required uint32 right = 2; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required uint32 top = 3; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required uint32 bottom = 4; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndTileBox) + } + + static { + defaultInstance = new OsmAndTileBox(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndTileBox) + } + + public static final class StringTable extends + com.google.protobuf.GeneratedMessage { + // Use StringTable.newBuilder() to construct. + private StringTable() { + initFields(); + } + private StringTable(boolean noInit) {} + + private static final StringTable defaultInstance; + public static StringTable getDefaultInstance() { + return defaultInstance; + } + + @Override + public StringTable getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_StringTable_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_StringTable_fieldAccessorTable; + } + + // repeated string s = 1; + public static final int S_FIELD_NUMBER = 1; + private java.util.List s_ = + java.util.Collections.emptyList(); + public java.util.List getSList() { + return s_; + } + public int getSCount() { return s_.size(); } + public java.lang.String getS(int index) { + return s_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (java.lang.String element : getSList()) { + output.writeString(1, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (java.lang.String element : getSList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getSList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.StringTable parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.StringTable parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StringTable parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.StringTable prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.StringTable result; + + // Construct using net.osmand.binary.OsmandOdb.StringTable.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.StringTable(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.StringTable internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.StringTable(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.StringTable.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.StringTable getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.StringTable build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.StringTable buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.StringTable buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.s_ != java.util.Collections.EMPTY_LIST) { + result.s_ = + java.util.Collections.unmodifiableList(result.s_); + } + net.osmand.binary.OsmandOdb.StringTable returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.StringTable) { + return mergeFrom((net.osmand.binary.OsmandOdb.StringTable)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.StringTable other) { + if (other == net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance()) return this; + if (!other.s_.isEmpty()) { + if (result.s_.isEmpty()) { + result.s_ = new java.util.ArrayList(); + } + result.s_.addAll(other.s_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + addS(input.readString()); + break; + } + } + } + } + + + // repeated string s = 1; + public java.util.List getSList() { + return java.util.Collections.unmodifiableList(result.s_); + } + public int getSCount() { + return result.getSCount(); + } + public java.lang.String getS(int index) { + return result.getS(index); + } + public Builder setS(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.s_.set(index, value); + return this; + } + public Builder addS(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.s_.isEmpty()) { + result.s_ = new java.util.ArrayList(); + } + result.s_.add(value); + return this; + } + public Builder addAllS( + java.lang.Iterable values) { + if (result.s_.isEmpty()) { + result.s_ = new java.util.ArrayList(); + } + super.addAll(values, result.s_); + return this; + } + public Builder clearS() { + result.s_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:StringTable) + } + + static { + defaultInstance = new StringTable(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:StringTable) + } + + public static final class IndexedStringTable extends + com.google.protobuf.GeneratedMessage { + // Use IndexedStringTable.newBuilder() to construct. + private IndexedStringTable() { + initFields(); + } + private IndexedStringTable(boolean noInit) {} + + private static final IndexedStringTable defaultInstance; + public static IndexedStringTable getDefaultInstance() { + return defaultInstance; + } + + @Override + public IndexedStringTable getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_IndexedStringTable_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_IndexedStringTable_fieldAccessorTable; + } + + // optional string prefix = 1; + public static final int PREFIX_FIELD_NUMBER = 1; + private boolean hasPrefix; + private java.lang.String prefix_ = ""; + public boolean hasPrefix() { return hasPrefix; } + public java.lang.String getPrefix() { return prefix_; } + + // repeated string key = 3; + public static final int KEY_FIELD_NUMBER = 3; + private java.util.List key_ = + java.util.Collections.emptyList(); + public java.util.List getKeyList() { + return key_; + } + public int getKeyCount() { return key_.size(); } + public java.lang.String getKey(int index) { + return key_.get(index); + } + + // repeated fixed32 val = 4; + public static final int VAL_FIELD_NUMBER = 4; + private java.util.List val_ = + java.util.Collections.emptyList(); + public java.util.List getValList() { + return val_; + } + public int getValCount() { return val_.size(); } + public int getVal(int index) { + return val_.get(index); + } + + // repeated .IndexedStringTable subtables = 5; + public static final int SUBTABLES_FIELD_NUMBER = 5; + private java.util.List subtables_ = + java.util.Collections.emptyList(); + public java.util.List getSubtablesList() { + return subtables_; + } + public int getSubtablesCount() { return subtables_.size(); } + public net.osmand.binary.OsmandOdb.IndexedStringTable getSubtables(int index) { + return subtables_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasPrefix()) { + output.writeString(1, getPrefix()); + } + for (java.lang.String element : getKeyList()) { + output.writeString(3, element); + } + for (int element : getValList()) { + output.writeFixed32(4, element); + } + for (net.osmand.binary.OsmandOdb.IndexedStringTable element : getSubtablesList()) { + output.writeMessage(5, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasPrefix()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getPrefix()); + } + { + int dataSize = 0; + for (java.lang.String element : getKeyList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getKeyList().size(); + } + { + int dataSize = 0; + dataSize = 4 * getValList().size(); + size += dataSize; + size += 1 * getValList().size(); + } + for (net.osmand.binary.OsmandOdb.IndexedStringTable element : getSubtablesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IndexedStringTable parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.IndexedStringTable prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.IndexedStringTable result; + + // Construct using net.osmand.binary.OsmandOdb.IndexedStringTable.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.IndexedStringTable(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.IndexedStringTable internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.IndexedStringTable(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.IndexedStringTable.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.IndexedStringTable getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.IndexedStringTable build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.IndexedStringTable buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.IndexedStringTable buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.key_ != java.util.Collections.EMPTY_LIST) { + result.key_ = + java.util.Collections.unmodifiableList(result.key_); + } + if (result.val_ != java.util.Collections.EMPTY_LIST) { + result.val_ = + java.util.Collections.unmodifiableList(result.val_); + } + if (result.subtables_ != java.util.Collections.EMPTY_LIST) { + result.subtables_ = + java.util.Collections.unmodifiableList(result.subtables_); + } + net.osmand.binary.OsmandOdb.IndexedStringTable returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.IndexedStringTable) { + return mergeFrom((net.osmand.binary.OsmandOdb.IndexedStringTable)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.IndexedStringTable other) { + if (other == net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance()) return this; + if (other.hasPrefix()) { + setPrefix(other.getPrefix()); + } + if (!other.key_.isEmpty()) { + if (result.key_.isEmpty()) { + result.key_ = new java.util.ArrayList(); + } + result.key_.addAll(other.key_); + } + if (!other.val_.isEmpty()) { + if (result.val_.isEmpty()) { + result.val_ = new java.util.ArrayList(); + } + result.val_.addAll(other.val_); + } + if (!other.subtables_.isEmpty()) { + if (result.subtables_.isEmpty()) { + result.subtables_ = new java.util.ArrayList(); + } + result.subtables_.addAll(other.subtables_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setPrefix(input.readString()); + break; + } + case 26: { + addKey(input.readString()); + break; + } + case 37: { + addVal(input.readFixed32()); + break; + } + case 34: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addVal(input.readFixed32()); + } + input.popLimit(limit); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.IndexedStringTable.Builder subBuilder = net.osmand.binary.OsmandOdb.IndexedStringTable.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addSubtables(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional string prefix = 1; + public boolean hasPrefix() { + return result.hasPrefix(); + } + public java.lang.String getPrefix() { + return result.getPrefix(); + } + public Builder setPrefix(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPrefix = true; + result.prefix_ = value; + return this; + } + public Builder clearPrefix() { + result.hasPrefix = false; + result.prefix_ = getDefaultInstance().getPrefix(); + return this; + } + + // repeated string key = 3; + public java.util.List getKeyList() { + return java.util.Collections.unmodifiableList(result.key_); + } + public int getKeyCount() { + return result.getKeyCount(); + } + public java.lang.String getKey(int index) { + return result.getKey(index); + } + public Builder setKey(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.key_.set(index, value); + return this; + } + public Builder addKey(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.key_.isEmpty()) { + result.key_ = new java.util.ArrayList(); + } + result.key_.add(value); + return this; + } + public Builder addAllKey( + java.lang.Iterable values) { + if (result.key_.isEmpty()) { + result.key_ = new java.util.ArrayList(); + } + super.addAll(values, result.key_); + return this; + } + public Builder clearKey() { + result.key_ = java.util.Collections.emptyList(); + return this; + } + + // repeated fixed32 val = 4; + public java.util.List getValList() { + return java.util.Collections.unmodifiableList(result.val_); + } + public int getValCount() { + return result.getValCount(); + } + public int getVal(int index) { + return result.getVal(index); + } + public Builder setVal(int index, int value) { + result.val_.set(index, value); + return this; + } + public Builder addVal(int value) { + if (result.val_.isEmpty()) { + result.val_ = new java.util.ArrayList(); + } + result.val_.add(value); + return this; + } + public Builder addAllVal( + java.lang.Iterable values) { + if (result.val_.isEmpty()) { + result.val_ = new java.util.ArrayList(); + } + super.addAll(values, result.val_); + return this; + } + public Builder clearVal() { + result.val_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .IndexedStringTable subtables = 5; + public java.util.List getSubtablesList() { + return java.util.Collections.unmodifiableList(result.subtables_); + } + public int getSubtablesCount() { + return result.getSubtablesCount(); + } + public net.osmand.binary.OsmandOdb.IndexedStringTable getSubtables(int index) { + return result.getSubtables(index); + } + public Builder setSubtables(int index, net.osmand.binary.OsmandOdb.IndexedStringTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.subtables_.set(index, value); + return this; + } + public Builder setSubtables(int index, net.osmand.binary.OsmandOdb.IndexedStringTable.Builder builderForValue) { + result.subtables_.set(index, builderForValue.build()); + return this; + } + public Builder addSubtables(net.osmand.binary.OsmandOdb.IndexedStringTable value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.subtables_.isEmpty()) { + result.subtables_ = new java.util.ArrayList(); + } + result.subtables_.add(value); + return this; + } + public Builder addSubtables(net.osmand.binary.OsmandOdb.IndexedStringTable.Builder builderForValue) { + if (result.subtables_.isEmpty()) { + result.subtables_ = new java.util.ArrayList(); + } + result.subtables_.add(builderForValue.build()); + return this; + } + public Builder addAllSubtables( + java.lang.Iterable values) { + if (result.subtables_.isEmpty()) { + result.subtables_ = new java.util.ArrayList(); + } + super.addAll(values, result.subtables_); + return this; + } + public Builder clearSubtables() { + result.subtables_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:IndexedStringTable) + } + + static { + defaultInstance = new IndexedStringTable(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:IndexedStringTable) + } + + public static final class OsmAndMapIndex extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndMapIndex.newBuilder() to construct. + private OsmAndMapIndex() { + initFields(); + } + private OsmAndMapIndex(boolean noInit) {} + + private static final OsmAndMapIndex defaultInstance; + public static OsmAndMapIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndMapIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_fieldAccessorTable; + } + + public static final class MapEncodingRule extends + com.google.protobuf.GeneratedMessage { + // Use MapEncodingRule.newBuilder() to construct. + private MapEncodingRule() { + initFields(); + } + private MapEncodingRule(boolean noInit) {} + + private static final MapEncodingRule defaultInstance; + public static MapEncodingRule getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapEncodingRule getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_MapEncodingRule_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_MapEncodingRule_fieldAccessorTable; + } + + // required string tag = 3; + public static final int TAG_FIELD_NUMBER = 3; + private boolean hasTag; + private java.lang.String tag_ = ""; + public boolean hasTag() { return hasTag; } + public java.lang.String getTag() { return tag_; } + + // optional string value = 5; + public static final int VALUE_FIELD_NUMBER = 5; + private boolean hasValue; + private java.lang.String value_ = ""; + public boolean hasValue() { return hasValue; } + public java.lang.String getValue() { return value_; } + + // optional uint32 id = 7; + public static final int ID_FIELD_NUMBER = 7; + private boolean hasId; + private int id_ = 0; + public boolean hasId() { return hasId; } + public int getId() { return id_; } + + // optional uint32 minZoom = 9; + public static final int MINZOOM_FIELD_NUMBER = 9; + private boolean hasMinZoom; + private int minZoom_ = 0; + public boolean hasMinZoom() { return hasMinZoom; } + public int getMinZoom() { return minZoom_; } + + // optional uint32 type = 10; + public static final int TYPE_FIELD_NUMBER = 10; + private boolean hasType; + private int type_ = 0; + public boolean hasType() { return hasType; } + public int getType() { return type_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasTag) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasTag()) { + output.writeString(3, getTag()); + } + if (hasValue()) { + output.writeString(5, getValue()); + } + if (hasId()) { + output.writeUInt32(7, getId()); + } + if (hasMinZoom()) { + output.writeUInt32(9, getMinZoom()); + } + if (hasType()) { + output.writeUInt32(10, getType()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasTag()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getTag()); + } + if (hasValue()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(5, getValue()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(7, getId()); + } + if (hasMinZoom()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(9, getMinZoom()); + } + if (hasType()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(10, getType()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.getDefaultInstance()) return this; + if (other.hasTag()) { + setTag(other.getTag()); + } + if (other.hasValue()) { + setValue(other.getValue()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasMinZoom()) { + setMinZoom(other.getMinZoom()); + } + if (other.hasType()) { + setType(other.getType()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 26: { + setTag(input.readString()); + break; + } + case 42: { + setValue(input.readString()); + break; + } + case 56: { + setId(input.readUInt32()); + break; + } + case 72: { + setMinZoom(input.readUInt32()); + break; + } + case 80: { + setType(input.readUInt32()); + break; + } + } + } + } + + + // required string tag = 3; + public boolean hasTag() { + return result.hasTag(); + } + public java.lang.String getTag() { + return result.getTag(); + } + public Builder setTag(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTag = true; + result.tag_ = value; + return this; + } + public Builder clearTag() { + result.hasTag = false; + result.tag_ = getDefaultInstance().getTag(); + return this; + } + + // optional string value = 5; + public boolean hasValue() { + return result.hasValue(); + } + public java.lang.String getValue() { + return result.getValue(); + } + public Builder setValue(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasValue = true; + result.value_ = value; + return this; + } + public Builder clearValue() { + result.hasValue = false; + result.value_ = getDefaultInstance().getValue(); + return this; + } + + // optional uint32 id = 7; + public boolean hasId() { + return result.hasId(); + } + public int getId() { + return result.getId(); + } + public Builder setId(int value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0; + return this; + } + + // optional uint32 minZoom = 9; + public boolean hasMinZoom() { + return result.hasMinZoom(); + } + public int getMinZoom() { + return result.getMinZoom(); + } + public Builder setMinZoom(int value) { + result.hasMinZoom = true; + result.minZoom_ = value; + return this; + } + public Builder clearMinZoom() { + result.hasMinZoom = false; + result.minZoom_ = 0; + return this; + } + + // optional uint32 type = 10; + public boolean hasType() { + return result.hasType(); + } + public int getType() { + return result.getType(); + } + public Builder setType(int value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder clearType() { + result.hasType = false; + result.type_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndMapIndex.MapEncodingRule) + } + + static { + defaultInstance = new MapEncodingRule(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndMapIndex.MapEncodingRule) + } + + public static final class MapRootLevel extends + com.google.protobuf.GeneratedMessage { + // Use MapRootLevel.newBuilder() to construct. + private MapRootLevel() { + initFields(); + } + private MapRootLevel(boolean noInit) {} + + private static final MapRootLevel defaultInstance; + public static MapRootLevel getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapRootLevel getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_MapRootLevel_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_MapRootLevel_fieldAccessorTable; + } + + // required int32 maxZoom = 1; + public static final int MAXZOOM_FIELD_NUMBER = 1; + private boolean hasMaxZoom; + private int maxZoom_ = 0; + public boolean hasMaxZoom() { return hasMaxZoom; } + public int getMaxZoom() { return maxZoom_; } + + // required int32 minZoom = 2; + public static final int MINZOOM_FIELD_NUMBER = 2; + private boolean hasMinZoom; + private int minZoom_ = 0; + public boolean hasMinZoom() { return hasMinZoom; } + public int getMinZoom() { return minZoom_; } + + // required int32 left = 3; + public static final int LEFT_FIELD_NUMBER = 3; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required int32 right = 4; + public static final int RIGHT_FIELD_NUMBER = 4; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required int32 top = 5; + public static final int TOP_FIELD_NUMBER = 5; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required int32 bottom = 6; + public static final int BOTTOM_FIELD_NUMBER = 6; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // repeated .OsmAndMapIndex.MapDataBox boxes = 7; + public static final int BOXES_FIELD_NUMBER = 7; + private java.util.List boxes_ = + java.util.Collections.emptyList(); + public java.util.List getBoxesList() { + return boxes_; + } + public int getBoxesCount() { return boxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox getBoxes(int index) { + return boxes_.get(index); + } + + // repeated .MapDataBlock blocks = 15; + public static final int BLOCKS_FIELD_NUMBER = 15; + private java.util.List blocks_ = + java.util.Collections.emptyList(); + public java.util.List getBlocksList() { + return blocks_; + } + public int getBlocksCount() { return blocks_.size(); } + public net.osmand.binary.OsmandOdb.MapDataBlock getBlocks(int index) { + return blocks_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasMaxZoom) return false; + if (!hasMinZoom) return false; + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox element : getBoxesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.MapDataBlock element : getBlocksList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasMaxZoom()) { + output.writeInt32(1, getMaxZoom()); + } + if (hasMinZoom()) { + output.writeInt32(2, getMinZoom()); + } + if (hasLeft()) { + output.writeInt32(3, getLeft()); + } + if (hasRight()) { + output.writeInt32(4, getRight()); + } + if (hasTop()) { + output.writeInt32(5, getTop()); + } + if (hasBottom()) { + output.writeInt32(6, getBottom()); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox element : getBoxesList()) { + output.writeMessage(7, element); + } + for (net.osmand.binary.OsmandOdb.MapDataBlock element : getBlocksList()) { + output.writeMessage(15, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasMaxZoom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, getMaxZoom()); + } + if (hasMinZoom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getMinZoom()); + } + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(6, getBottom()); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox element : getBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + for (net.osmand.binary.OsmandOdb.MapDataBlock element : getBlocksList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(15, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.boxes_ != java.util.Collections.EMPTY_LIST) { + result.boxes_ = + java.util.Collections.unmodifiableList(result.boxes_); + } + if (result.blocks_ != java.util.Collections.EMPTY_LIST) { + result.blocks_ = + java.util.Collections.unmodifiableList(result.blocks_); + } + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.getDefaultInstance()) return this; + if (other.hasMaxZoom()) { + setMaxZoom(other.getMaxZoom()); + } + if (other.hasMinZoom()) { + setMinZoom(other.getMinZoom()); + } + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (!other.boxes_.isEmpty()) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.addAll(other.boxes_); + } + if (!other.blocks_.isEmpty()) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.addAll(other.blocks_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setMaxZoom(input.readInt32()); + break; + } + case 16: { + setMinZoom(input.readInt32()); + break; + } + case 24: { + setLeft(input.readInt32()); + break; + } + case 32: { + setRight(input.readInt32()); + break; + } + case 40: { + setTop(input.readInt32()); + break; + } + case 48: { + setBottom(input.readInt32()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBoxes(subBuilder.buildPartial()); + break; + } + case 122: { + net.osmand.binary.OsmandOdb.MapDataBlock.Builder subBuilder = net.osmand.binary.OsmandOdb.MapDataBlock.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBlocks(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required int32 maxZoom = 1; + public boolean hasMaxZoom() { + return result.hasMaxZoom(); + } + public int getMaxZoom() { + return result.getMaxZoom(); + } + public Builder setMaxZoom(int value) { + result.hasMaxZoom = true; + result.maxZoom_ = value; + return this; + } + public Builder clearMaxZoom() { + result.hasMaxZoom = false; + result.maxZoom_ = 0; + return this; + } + + // required int32 minZoom = 2; + public boolean hasMinZoom() { + return result.hasMinZoom(); + } + public int getMinZoom() { + return result.getMinZoom(); + } + public Builder setMinZoom(int value) { + result.hasMinZoom = true; + result.minZoom_ = value; + return this; + } + public Builder clearMinZoom() { + result.hasMinZoom = false; + result.minZoom_ = 0; + return this; + } + + // required int32 left = 3; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required int32 right = 4; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required int32 top = 5; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required int32 bottom = 6; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // repeated .OsmAndMapIndex.MapDataBox boxes = 7; + public java.util.List getBoxesList() { + return java.util.Collections.unmodifiableList(result.boxes_); + } + public int getBoxesCount() { + return result.getBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox getBoxes(int index) { + return result.getBoxes(index); + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.boxes_.set(index, value); + return this; + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder builderForValue) { + result.boxes_.set(index, builderForValue.build()); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(value); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder builderForValue) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(builderForValue.build()); + return this; + } + public Builder addAllBoxes( + java.lang.Iterable values) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.boxes_); + return this; + } + public Builder clearBoxes() { + result.boxes_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .MapDataBlock blocks = 15; + public java.util.List getBlocksList() { + return java.util.Collections.unmodifiableList(result.blocks_); + } + public int getBlocksCount() { + return result.getBlocksCount(); + } + public net.osmand.binary.OsmandOdb.MapDataBlock getBlocks(int index) { + return result.getBlocks(index); + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.MapDataBlock value) { + if (value == null) { + throw new NullPointerException(); + } + result.blocks_.set(index, value); + return this; + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.MapDataBlock.Builder builderForValue) { + result.blocks_.set(index, builderForValue.build()); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.MapDataBlock value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(value); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.MapDataBlock.Builder builderForValue) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(builderForValue.build()); + return this; + } + public Builder addAllBlocks( + java.lang.Iterable values) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + super.addAll(values, result.blocks_); + return this; + } + public Builder clearBlocks() { + result.blocks_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndMapIndex.MapRootLevel) + } + + static { + defaultInstance = new MapRootLevel(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndMapIndex.MapRootLevel) + } + + public static final class MapDataBox extends + com.google.protobuf.GeneratedMessage { + // Use MapDataBox.newBuilder() to construct. + private MapDataBox() { + initFields(); + } + private MapDataBox(boolean noInit) {} + + private static final MapDataBox defaultInstance; + public static MapDataBox getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapDataBox getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_MapDataBox_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndMapIndex_MapDataBox_fieldAccessorTable; + } + + // required sint32 left = 1; + public static final int LEFT_FIELD_NUMBER = 1; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required sint32 right = 2; + public static final int RIGHT_FIELD_NUMBER = 2; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required sint32 top = 3; + public static final int TOP_FIELD_NUMBER = 3; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required sint32 bottom = 4; + public static final int BOTTOM_FIELD_NUMBER = 4; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // optional fixed32 shiftToMapData = 5; + public static final int SHIFTTOMAPDATA_FIELD_NUMBER = 5; + private boolean hasShiftToMapData; + private int shiftToMapData_ = 0; + public boolean hasShiftToMapData() { return hasShiftToMapData; } + public int getShiftToMapData() { return shiftToMapData_; } + + // optional bool ocean = 6; + public static final int OCEAN_FIELD_NUMBER = 6; + private boolean hasOcean; + private boolean ocean_ = false; + public boolean hasOcean() { return hasOcean; } + public boolean getOcean() { return ocean_; } + + // repeated .OsmAndMapIndex.MapDataBox boxes = 7; + public static final int BOXES_FIELD_NUMBER = 7; + private java.util.List boxes_ = + java.util.Collections.emptyList(); + public java.util.List getBoxesList() { + return boxes_; + } + public int getBoxesCount() { return boxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox getBoxes(int index) { + return boxes_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox element : getBoxesList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasLeft()) { + output.writeSInt32(1, getLeft()); + } + if (hasRight()) { + output.writeSInt32(2, getRight()); + } + if (hasTop()) { + output.writeSInt32(3, getTop()); + } + if (hasBottom()) { + output.writeSInt32(4, getBottom()); + } + if (hasShiftToMapData()) { + output.writeFixed32(5, getShiftToMapData()); + } + if (hasOcean()) { + output.writeBool(6, getOcean()); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox element : getBoxesList()) { + output.writeMessage(7, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(1, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(4, getBottom()); + } + if (hasShiftToMapData()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(5, getShiftToMapData()); + } + if (hasOcean()) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(6, getOcean()); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox element : getBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.boxes_ != java.util.Collections.EMPTY_LIST) { + result.boxes_ = + java.util.Collections.unmodifiableList(result.boxes_); + } + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.getDefaultInstance()) return this; + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (other.hasShiftToMapData()) { + setShiftToMapData(other.getShiftToMapData()); + } + if (other.hasOcean()) { + setOcean(other.getOcean()); + } + if (!other.boxes_.isEmpty()) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.addAll(other.boxes_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setLeft(input.readSInt32()); + break; + } + case 16: { + setRight(input.readSInt32()); + break; + } + case 24: { + setTop(input.readSInt32()); + break; + } + case 32: { + setBottom(input.readSInt32()); + break; + } + case 45: { + setShiftToMapData(input.readFixed32()); + break; + } + case 48: { + setOcean(input.readBool()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBoxes(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required sint32 left = 1; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required sint32 right = 2; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required sint32 top = 3; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required sint32 bottom = 4; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // optional fixed32 shiftToMapData = 5; + public boolean hasShiftToMapData() { + return result.hasShiftToMapData(); + } + public int getShiftToMapData() { + return result.getShiftToMapData(); + } + public Builder setShiftToMapData(int value) { + result.hasShiftToMapData = true; + result.shiftToMapData_ = value; + return this; + } + public Builder clearShiftToMapData() { + result.hasShiftToMapData = false; + result.shiftToMapData_ = 0; + return this; + } + + // optional bool ocean = 6; + public boolean hasOcean() { + return result.hasOcean(); + } + public boolean getOcean() { + return result.getOcean(); + } + public Builder setOcean(boolean value) { + result.hasOcean = true; + result.ocean_ = value; + return this; + } + public Builder clearOcean() { + result.hasOcean = false; + result.ocean_ = false; + return this; + } + + // repeated .OsmAndMapIndex.MapDataBox boxes = 7; + public java.util.List getBoxesList() { + return java.util.Collections.unmodifiableList(result.boxes_); + } + public int getBoxesCount() { + return result.getBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox getBoxes(int index) { + return result.getBoxes(index); + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.boxes_.set(index, value); + return this; + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder builderForValue) { + result.boxes_.set(index, builderForValue.build()); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(value); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder builderForValue) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(builderForValue.build()); + return this; + } + public Builder addAllBoxes( + java.lang.Iterable values) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.boxes_); + return this; + } + public Builder clearBoxes() { + result.boxes_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndMapIndex.MapDataBox) + } + + static { + defaultInstance = new MapDataBox(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndMapIndex.MapDataBox) + } + + // required string name = 2; + public static final int NAME_FIELD_NUMBER = 2; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // repeated .OsmAndMapIndex.MapEncodingRule rules = 4; + public static final int RULES_FIELD_NUMBER = 4; + private java.util.List rules_ = + java.util.Collections.emptyList(); + public java.util.List getRulesList() { + return rules_; + } + public int getRulesCount() { return rules_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule getRules(int index) { + return rules_.get(index); + } + + // repeated .OsmAndMapIndex.MapRootLevel levels = 5; + public static final int LEVELS_FIELD_NUMBER = 5; + private java.util.List levels_ = + java.util.Collections.emptyList(); + public java.util.List getLevelsList() { + return levels_; + } + public int getLevelsCount() { return levels_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel getLevels(int index) { + return levels_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule element : getRulesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel element : getLevelsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(2, getName()); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule element : getRulesList()) { + output.writeMessage(4, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel element : getLevelsList()) { + output.writeMessage(5, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getName()); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule element : getRulesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel element : getLevelsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndMapIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndMapIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndMapIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndMapIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndMapIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndMapIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndMapIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndMapIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndMapIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.rules_ != java.util.Collections.EMPTY_LIST) { + result.rules_ = + java.util.Collections.unmodifiableList(result.rules_); + } + if (result.levels_ != java.util.Collections.EMPTY_LIST) { + result.levels_ = + java.util.Collections.unmodifiableList(result.levels_); + } + net.osmand.binary.OsmandOdb.OsmAndMapIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndMapIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndMapIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndMapIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndMapIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (!other.rules_.isEmpty()) { + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + result.rules_.addAll(other.rules_); + } + if (!other.levels_.isEmpty()) { + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + result.levels_.addAll(other.levels_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 18: { + setName(input.readString()); + break; + } + case 34: { + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRules(subBuilder.buildPartial()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addLevels(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required string name = 2; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // repeated .OsmAndMapIndex.MapEncodingRule rules = 4; + public java.util.List getRulesList() { + return java.util.Collections.unmodifiableList(result.rules_); + } + public int getRulesCount() { + return result.getRulesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule getRules(int index) { + return result.getRules(index); + } + public Builder setRules(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule value) { + if (value == null) { + throw new NullPointerException(); + } + result.rules_.set(index, value); + return this; + } + public Builder setRules(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.Builder builderForValue) { + result.rules_.set(index, builderForValue.build()); + return this; + } + public Builder addRules(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + result.rules_.add(value); + return this; + } + public Builder addRules(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.Builder builderForValue) { + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + result.rules_.add(builderForValue.build()); + return this; + } + public Builder addAllRules( + java.lang.Iterable values) { + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + super.addAll(values, result.rules_); + return this; + } + public Builder clearRules() { + result.rules_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndMapIndex.MapRootLevel levels = 5; + public java.util.List getLevelsList() { + return java.util.Collections.unmodifiableList(result.levels_); + } + public int getLevelsCount() { + return result.getLevelsCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel getLevels(int index) { + return result.getLevels(index); + } + public Builder setLevels(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel value) { + if (value == null) { + throw new NullPointerException(); + } + result.levels_.set(index, value); + return this; + } + public Builder setLevels(int index, net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.Builder builderForValue) { + result.levels_.set(index, builderForValue.build()); + return this; + } + public Builder addLevels(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + result.levels_.add(value); + return this; + } + public Builder addLevels(net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.Builder builderForValue) { + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + result.levels_.add(builderForValue.build()); + return this; + } + public Builder addAllLevels( + java.lang.Iterable values) { + if (result.levels_.isEmpty()) { + result.levels_ = new java.util.ArrayList(); + } + super.addAll(values, result.levels_); + return this; + } + public Builder clearLevels() { + result.levels_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndMapIndex) + } + + static { + defaultInstance = new OsmAndMapIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndMapIndex) + } + + public static final class MapDataBlock extends + com.google.protobuf.GeneratedMessage { + // Use MapDataBlock.newBuilder() to construct. + private MapDataBlock() { + initFields(); + } + private MapDataBlock(boolean noInit) {} + + private static final MapDataBlock defaultInstance; + public static MapDataBlock getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapDataBlock getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_MapDataBlock_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_MapDataBlock_fieldAccessorTable; + } + + // optional uint64 baseId = 10; + public static final int BASEID_FIELD_NUMBER = 10; + private boolean hasBaseId; + private long baseId_ = 0L; + public boolean hasBaseId() { return hasBaseId; } + public long getBaseId() { return baseId_; } + + // repeated .MapData dataObjects = 12; + public static final int DATAOBJECTS_FIELD_NUMBER = 12; + private java.util.List dataObjects_ = + java.util.Collections.emptyList(); + public java.util.List getDataObjectsList() { + return dataObjects_; + } + public int getDataObjectsCount() { return dataObjects_.size(); } + public net.osmand.binary.OsmandOdb.MapData getDataObjects(int index) { + return dataObjects_.get(index); + } + + // optional .StringTable stringTable = 15; + public static final int STRINGTABLE_FIELD_NUMBER = 15; + private boolean hasStringTable; + private net.osmand.binary.OsmandOdb.StringTable stringTable_; + public boolean hasStringTable() { return hasStringTable; } + public net.osmand.binary.OsmandOdb.StringTable getStringTable() { return stringTable_; } + + private void initFields() { + stringTable_ = net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + for (net.osmand.binary.OsmandOdb.MapData element : getDataObjectsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasBaseId()) { + output.writeUInt64(10, getBaseId()); + } + for (net.osmand.binary.OsmandOdb.MapData element : getDataObjectsList()) { + output.writeMessage(12, element); + } + if (hasStringTable()) { + output.writeMessage(15, getStringTable()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasBaseId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(10, getBaseId()); + } + for (net.osmand.binary.OsmandOdb.MapData element : getDataObjectsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(12, element); + } + if (hasStringTable()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(15, getStringTable()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapDataBlock parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.MapDataBlock prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.MapDataBlock result; + + // Construct using net.osmand.binary.OsmandOdb.MapDataBlock.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.MapDataBlock(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.MapDataBlock internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.MapDataBlock(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.MapDataBlock.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.MapDataBlock getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.MapDataBlock.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.MapDataBlock build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.MapDataBlock buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.MapDataBlock buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.dataObjects_ != java.util.Collections.EMPTY_LIST) { + result.dataObjects_ = + java.util.Collections.unmodifiableList(result.dataObjects_); + } + net.osmand.binary.OsmandOdb.MapDataBlock returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.MapDataBlock) { + return mergeFrom((net.osmand.binary.OsmandOdb.MapDataBlock)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.MapDataBlock other) { + if (other == net.osmand.binary.OsmandOdb.MapDataBlock.getDefaultInstance()) return this; + if (other.hasBaseId()) { + setBaseId(other.getBaseId()); + } + if (!other.dataObjects_.isEmpty()) { + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + result.dataObjects_.addAll(other.dataObjects_); + } + if (other.hasStringTable()) { + mergeStringTable(other.getStringTable()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 80: { + setBaseId(input.readUInt64()); + break; + } + case 98: { + net.osmand.binary.OsmandOdb.MapData.Builder subBuilder = net.osmand.binary.OsmandOdb.MapData.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addDataObjects(subBuilder.buildPartial()); + break; + } + case 122: { + net.osmand.binary.OsmandOdb.StringTable.Builder subBuilder = net.osmand.binary.OsmandOdb.StringTable.newBuilder(); + if (hasStringTable()) { + subBuilder.mergeFrom(getStringTable()); + } + input.readMessage(subBuilder, extensionRegistry); + setStringTable(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional uint64 baseId = 10; + public boolean hasBaseId() { + return result.hasBaseId(); + } + public long getBaseId() { + return result.getBaseId(); + } + public Builder setBaseId(long value) { + result.hasBaseId = true; + result.baseId_ = value; + return this; + } + public Builder clearBaseId() { + result.hasBaseId = false; + result.baseId_ = 0L; + return this; + } + + // repeated .MapData dataObjects = 12; + public java.util.List getDataObjectsList() { + return java.util.Collections.unmodifiableList(result.dataObjects_); + } + public int getDataObjectsCount() { + return result.getDataObjectsCount(); + } + public net.osmand.binary.OsmandOdb.MapData getDataObjects(int index) { + return result.getDataObjects(index); + } + public Builder setDataObjects(int index, net.osmand.binary.OsmandOdb.MapData value) { + if (value == null) { + throw new NullPointerException(); + } + result.dataObjects_.set(index, value); + return this; + } + public Builder setDataObjects(int index, net.osmand.binary.OsmandOdb.MapData.Builder builderForValue) { + result.dataObjects_.set(index, builderForValue.build()); + return this; + } + public Builder addDataObjects(net.osmand.binary.OsmandOdb.MapData value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + result.dataObjects_.add(value); + return this; + } + public Builder addDataObjects(net.osmand.binary.OsmandOdb.MapData.Builder builderForValue) { + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + result.dataObjects_.add(builderForValue.build()); + return this; + } + public Builder addAllDataObjects( + java.lang.Iterable values) { + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + super.addAll(values, result.dataObjects_); + return this; + } + public Builder clearDataObjects() { + result.dataObjects_ = java.util.Collections.emptyList(); + return this; + } + + // optional .StringTable stringTable = 15; + public boolean hasStringTable() { + return result.hasStringTable(); + } + public net.osmand.binary.OsmandOdb.StringTable getStringTable() { + return result.getStringTable(); + } + public Builder setStringTable(net.osmand.binary.OsmandOdb.StringTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasStringTable = true; + result.stringTable_ = value; + return this; + } + public Builder setStringTable(net.osmand.binary.OsmandOdb.StringTable.Builder builderForValue) { + result.hasStringTable = true; + result.stringTable_ = builderForValue.build(); + return this; + } + public Builder mergeStringTable(net.osmand.binary.OsmandOdb.StringTable value) { + if (result.hasStringTable() && + result.stringTable_ != net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance()) { + result.stringTable_ = + net.osmand.binary.OsmandOdb.StringTable.newBuilder(result.stringTable_).mergeFrom(value).buildPartial(); + } else { + result.stringTable_ = value; + } + result.hasStringTable = true; + return this; + } + public Builder clearStringTable() { + result.hasStringTable = false; + result.stringTable_ = net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:MapDataBlock) + } + + static { + defaultInstance = new MapDataBlock(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:MapDataBlock) + } + + public static final class MapData extends + com.google.protobuf.GeneratedMessage { + // Use MapData.newBuilder() to construct. + private MapData() { + initFields(); + } + private MapData(boolean noInit) {} + + private static final MapData defaultInstance; + public static MapData getDefaultInstance() { + return defaultInstance; + } + + @Override + public MapData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_MapData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_MapData_fieldAccessorTable; + } + + // optional bytes coordinates = 1; + public static final int COORDINATES_FIELD_NUMBER = 1; + private boolean hasCoordinates; + private com.google.protobuf.ByteString coordinates_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasCoordinates() { return hasCoordinates; } + public com.google.protobuf.ByteString getCoordinates() { return coordinates_; } + + // optional bytes areaCoordinates = 2; + public static final int AREACOORDINATES_FIELD_NUMBER = 2; + private boolean hasAreaCoordinates; + private com.google.protobuf.ByteString areaCoordinates_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasAreaCoordinates() { return hasAreaCoordinates; } + public com.google.protobuf.ByteString getAreaCoordinates() { return areaCoordinates_; } + + // repeated bytes polygonInnerCoordinates = 4; + public static final int POLYGONINNERCOORDINATES_FIELD_NUMBER = 4; + private java.util.List polygonInnerCoordinates_ = + java.util.Collections.emptyList(); + public java.util.List getPolygonInnerCoordinatesList() { + return polygonInnerCoordinates_; + } + public int getPolygonInnerCoordinatesCount() { return polygonInnerCoordinates_.size(); } + public com.google.protobuf.ByteString getPolygonInnerCoordinates(int index) { + return polygonInnerCoordinates_.get(index); + } + + // optional bytes additionalTypes = 6; + public static final int ADDITIONALTYPES_FIELD_NUMBER = 6; + private boolean hasAdditionalTypes; + private com.google.protobuf.ByteString additionalTypes_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasAdditionalTypes() { return hasAdditionalTypes; } + public com.google.protobuf.ByteString getAdditionalTypes() { return additionalTypes_; } + + // required bytes types = 7; + public static final int TYPES_FIELD_NUMBER = 7; + private boolean hasTypes; + private com.google.protobuf.ByteString types_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasTypes() { return hasTypes; } + public com.google.protobuf.ByteString getTypes() { return types_; } + + // optional bytes stringNames = 10; + public static final int STRINGNAMES_FIELD_NUMBER = 10; + private boolean hasStringNames; + private com.google.protobuf.ByteString stringNames_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasStringNames() { return hasStringNames; } + public com.google.protobuf.ByteString getStringNames() { return stringNames_; } + + // required sint64 id = 12; + public static final int ID_FIELD_NUMBER = 12; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // optional bytes rasterBytes = 15; + public static final int RASTERBYTES_FIELD_NUMBER = 15; + private boolean hasRasterBytes; + private com.google.protobuf.ByteString rasterBytes_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasRasterBytes() { return hasRasterBytes; } + public com.google.protobuf.ByteString getRasterBytes() { return rasterBytes_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasTypes) return false; + if (!hasId) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasCoordinates()) { + output.writeBytes(1, getCoordinates()); + } + if (hasAreaCoordinates()) { + output.writeBytes(2, getAreaCoordinates()); + } + for (com.google.protobuf.ByteString element : getPolygonInnerCoordinatesList()) { + output.writeBytes(4, element); + } + if (hasAdditionalTypes()) { + output.writeBytes(6, getAdditionalTypes()); + } + if (hasTypes()) { + output.writeBytes(7, getTypes()); + } + if (hasStringNames()) { + output.writeBytes(10, getStringNames()); + } + if (hasId()) { + output.writeSInt64(12, getId()); + } + if (hasRasterBytes()) { + output.writeBytes(15, getRasterBytes()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasCoordinates()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, getCoordinates()); + } + if (hasAreaCoordinates()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, getAreaCoordinates()); + } + { + int dataSize = 0; + for (com.google.protobuf.ByteString element : getPolygonInnerCoordinatesList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeBytesSizeNoTag(element); + } + size += dataSize; + size += 1 * getPolygonInnerCoordinatesList().size(); + } + if (hasAdditionalTypes()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(6, getAdditionalTypes()); + } + if (hasTypes()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(7, getTypes()); + } + if (hasStringNames()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(10, getStringNames()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt64Size(12, getId()); + } + if (hasRasterBytes()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(15, getRasterBytes()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.MapData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.MapData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.MapData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.MapData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.MapData result; + + // Construct using net.osmand.binary.OsmandOdb.MapData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.MapData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.MapData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.MapData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.MapData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.MapData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.MapData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.MapData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.MapData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.MapData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.polygonInnerCoordinates_ != java.util.Collections.EMPTY_LIST) { + result.polygonInnerCoordinates_ = + java.util.Collections.unmodifiableList(result.polygonInnerCoordinates_); + } + net.osmand.binary.OsmandOdb.MapData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.MapData) { + return mergeFrom((net.osmand.binary.OsmandOdb.MapData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.MapData other) { + if (other == net.osmand.binary.OsmandOdb.MapData.getDefaultInstance()) return this; + if (other.hasCoordinates()) { + setCoordinates(other.getCoordinates()); + } + if (other.hasAreaCoordinates()) { + setAreaCoordinates(other.getAreaCoordinates()); + } + if (!other.polygonInnerCoordinates_.isEmpty()) { + if (result.polygonInnerCoordinates_.isEmpty()) { + result.polygonInnerCoordinates_ = new java.util.ArrayList(); + } + result.polygonInnerCoordinates_.addAll(other.polygonInnerCoordinates_); + } + if (other.hasAdditionalTypes()) { + setAdditionalTypes(other.getAdditionalTypes()); + } + if (other.hasTypes()) { + setTypes(other.getTypes()); + } + if (other.hasStringNames()) { + setStringNames(other.getStringNames()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasRasterBytes()) { + setRasterBytes(other.getRasterBytes()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setCoordinates(input.readBytes()); + break; + } + case 18: { + setAreaCoordinates(input.readBytes()); + break; + } + case 34: { + addPolygonInnerCoordinates(input.readBytes()); + break; + } + case 50: { + setAdditionalTypes(input.readBytes()); + break; + } + case 58: { + setTypes(input.readBytes()); + break; + } + case 82: { + setStringNames(input.readBytes()); + break; + } + case 96: { + setId(input.readSInt64()); + break; + } + case 122: { + setRasterBytes(input.readBytes()); + break; + } + } + } + } + + + // optional bytes coordinates = 1; + public boolean hasCoordinates() { + return result.hasCoordinates(); + } + public com.google.protobuf.ByteString getCoordinates() { + return result.getCoordinates(); + } + public Builder setCoordinates(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasCoordinates = true; + result.coordinates_ = value; + return this; + } + public Builder clearCoordinates() { + result.hasCoordinates = false; + result.coordinates_ = getDefaultInstance().getCoordinates(); + return this; + } + + // optional bytes areaCoordinates = 2; + public boolean hasAreaCoordinates() { + return result.hasAreaCoordinates(); + } + public com.google.protobuf.ByteString getAreaCoordinates() { + return result.getAreaCoordinates(); + } + public Builder setAreaCoordinates(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasAreaCoordinates = true; + result.areaCoordinates_ = value; + return this; + } + public Builder clearAreaCoordinates() { + result.hasAreaCoordinates = false; + result.areaCoordinates_ = getDefaultInstance().getAreaCoordinates(); + return this; + } + + // repeated bytes polygonInnerCoordinates = 4; + public java.util.List getPolygonInnerCoordinatesList() { + return java.util.Collections.unmodifiableList(result.polygonInnerCoordinates_); + } + public int getPolygonInnerCoordinatesCount() { + return result.getPolygonInnerCoordinatesCount(); + } + public com.google.protobuf.ByteString getPolygonInnerCoordinates(int index) { + return result.getPolygonInnerCoordinates(index); + } + public Builder setPolygonInnerCoordinates(int index, com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.polygonInnerCoordinates_.set(index, value); + return this; + } + public Builder addPolygonInnerCoordinates(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.polygonInnerCoordinates_.isEmpty()) { + result.polygonInnerCoordinates_ = new java.util.ArrayList(); + } + result.polygonInnerCoordinates_.add(value); + return this; + } + public Builder addAllPolygonInnerCoordinates( + java.lang.Iterable values) { + if (result.polygonInnerCoordinates_.isEmpty()) { + result.polygonInnerCoordinates_ = new java.util.ArrayList(); + } + super.addAll(values, result.polygonInnerCoordinates_); + return this; + } + public Builder clearPolygonInnerCoordinates() { + result.polygonInnerCoordinates_ = java.util.Collections.emptyList(); + return this; + } + + // optional bytes additionalTypes = 6; + public boolean hasAdditionalTypes() { + return result.hasAdditionalTypes(); + } + public com.google.protobuf.ByteString getAdditionalTypes() { + return result.getAdditionalTypes(); + } + public Builder setAdditionalTypes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasAdditionalTypes = true; + result.additionalTypes_ = value; + return this; + } + public Builder clearAdditionalTypes() { + result.hasAdditionalTypes = false; + result.additionalTypes_ = getDefaultInstance().getAdditionalTypes(); + return this; + } + + // required bytes types = 7; + public boolean hasTypes() { + return result.hasTypes(); + } + public com.google.protobuf.ByteString getTypes() { + return result.getTypes(); + } + public Builder setTypes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTypes = true; + result.types_ = value; + return this; + } + public Builder clearTypes() { + result.hasTypes = false; + result.types_ = getDefaultInstance().getTypes(); + return this; + } + + // optional bytes stringNames = 10; + public boolean hasStringNames() { + return result.hasStringNames(); + } + public com.google.protobuf.ByteString getStringNames() { + return result.getStringNames(); + } + public Builder setStringNames(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasStringNames = true; + result.stringNames_ = value; + return this; + } + public Builder clearStringNames() { + result.hasStringNames = false; + result.stringNames_ = getDefaultInstance().getStringNames(); + return this; + } + + // required sint64 id = 12; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // optional bytes rasterBytes = 15; + public boolean hasRasterBytes() { + return result.hasRasterBytes(); + } + public com.google.protobuf.ByteString getRasterBytes() { + return result.getRasterBytes(); + } + public Builder setRasterBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasRasterBytes = true; + result.rasterBytes_ = value; + return this; + } + public Builder clearRasterBytes() { + result.hasRasterBytes = false; + result.rasterBytes_ = getDefaultInstance().getRasterBytes(); + return this; + } + + // @@protoc_insertion_point(builder_scope:MapData) + } + + static { + defaultInstance = new MapData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:MapData) + } + + public static final class OsmAndAddressIndex extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndAddressIndex.newBuilder() to construct. + private OsmAndAddressIndex() { + initFields(); + } + private OsmAndAddressIndex(boolean noInit) {} + + private static final OsmAndAddressIndex defaultInstance; + public static OsmAndAddressIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndAddressIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressIndex_fieldAccessorTable; + } + + public static final class CitiesIndex extends + com.google.protobuf.GeneratedMessage { + // Use CitiesIndex.newBuilder() to construct. + private CitiesIndex() { + initFields(); + } + private CitiesIndex(boolean noInit) {} + + private static final CitiesIndex defaultInstance; + public static CitiesIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public CitiesIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressIndex_CitiesIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressIndex_CitiesIndex_fieldAccessorTable; + } + + // required uint32 type = 2; + public static final int TYPE_FIELD_NUMBER = 2; + private boolean hasType; + private int type_ = 0; + public boolean hasType() { return hasType; } + public int getType() { return type_; } + + // repeated .CityIndex cities = 5; + public static final int CITIES_FIELD_NUMBER = 5; + private java.util.List cities_ = + java.util.Collections.emptyList(); + public java.util.List getCitiesList() { + return cities_; + } + public int getCitiesCount() { return cities_.size(); } + public net.osmand.binary.OsmandOdb.CityIndex getCities(int index) { + return cities_.get(index); + } + + // repeated .CityBlockIndex blocks = 7; + public static final int BLOCKS_FIELD_NUMBER = 7; + private java.util.List blocks_ = + java.util.Collections.emptyList(); + public java.util.List getBlocksList() { + return blocks_; + } + public int getBlocksCount() { return blocks_.size(); } + public net.osmand.binary.OsmandOdb.CityBlockIndex getBlocks(int index) { + return blocks_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasType) return false; + for (net.osmand.binary.OsmandOdb.CityIndex element : getCitiesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.CityBlockIndex element : getBlocksList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasType()) { + output.writeUInt32(2, getType()); + } + for (net.osmand.binary.OsmandOdb.CityIndex element : getCitiesList()) { + output.writeMessage(5, element); + } + for (net.osmand.binary.OsmandOdb.CityBlockIndex element : getBlocksList()) { + output.writeMessage(7, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasType()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(2, getType()); + } + for (net.osmand.binary.OsmandOdb.CityIndex element : getCitiesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + for (net.osmand.binary.OsmandOdb.CityBlockIndex element : getBlocksList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.cities_ != java.util.Collections.EMPTY_LIST) { + result.cities_ = + java.util.Collections.unmodifiableList(result.cities_); + } + if (result.blocks_ != java.util.Collections.EMPTY_LIST) { + result.blocks_ = + java.util.Collections.unmodifiableList(result.blocks_); + } + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.getDefaultInstance()) return this; + if (other.hasType()) { + setType(other.getType()); + } + if (!other.cities_.isEmpty()) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.addAll(other.cities_); + } + if (!other.blocks_.isEmpty()) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.addAll(other.blocks_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 16: { + setType(input.readUInt32()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.CityIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.CityIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addCities(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.CityBlockIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.CityBlockIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBlocks(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required uint32 type = 2; + public boolean hasType() { + return result.hasType(); + } + public int getType() { + return result.getType(); + } + public Builder setType(int value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder clearType() { + result.hasType = false; + result.type_ = 0; + return this; + } + + // repeated .CityIndex cities = 5; + public java.util.List getCitiesList() { + return java.util.Collections.unmodifiableList(result.cities_); + } + public int getCitiesCount() { + return result.getCitiesCount(); + } + public net.osmand.binary.OsmandOdb.CityIndex getCities(int index) { + return result.getCities(index); + } + public Builder setCities(int index, net.osmand.binary.OsmandOdb.CityIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.cities_.set(index, value); + return this; + } + public Builder setCities(int index, net.osmand.binary.OsmandOdb.CityIndex.Builder builderForValue) { + result.cities_.set(index, builderForValue.build()); + return this; + } + public Builder addCities(net.osmand.binary.OsmandOdb.CityIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.add(value); + return this; + } + public Builder addCities(net.osmand.binary.OsmandOdb.CityIndex.Builder builderForValue) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.add(builderForValue.build()); + return this; + } + public Builder addAllCities( + java.lang.Iterable values) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + super.addAll(values, result.cities_); + return this; + } + public Builder clearCities() { + result.cities_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .CityBlockIndex blocks = 7; + public java.util.List getBlocksList() { + return java.util.Collections.unmodifiableList(result.blocks_); + } + public int getBlocksCount() { + return result.getBlocksCount(); + } + public net.osmand.binary.OsmandOdb.CityBlockIndex getBlocks(int index) { + return result.getBlocks(index); + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.CityBlockIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.blocks_.set(index, value); + return this; + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.CityBlockIndex.Builder builderForValue) { + result.blocks_.set(index, builderForValue.build()); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.CityBlockIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(value); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.CityBlockIndex.Builder builderForValue) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(builderForValue.build()); + return this; + } + public Builder addAllBlocks( + java.lang.Iterable values) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + super.addAll(values, result.blocks_); + return this; + } + public Builder clearBlocks() { + result.blocks_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndAddressIndex.CitiesIndex) + } + + static { + defaultInstance = new CitiesIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndAddressIndex.CitiesIndex) + } + + // required string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string name_en = 2; + public static final int NAME_EN_FIELD_NUMBER = 2; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // optional .OsmAndTileBox boundaries = 3; + public static final int BOUNDARIES_FIELD_NUMBER = 3; + private boolean hasBoundaries; + private net.osmand.binary.OsmandOdb.OsmAndTileBox boundaries_; + public boolean hasBoundaries() { return hasBoundaries; } + public net.osmand.binary.OsmandOdb.OsmAndTileBox getBoundaries() { return boundaries_; } + + // repeated .OsmAndAddressIndex.CitiesIndex cities = 6; + public static final int CITIES_FIELD_NUMBER = 6; + private java.util.List cities_ = + java.util.Collections.emptyList(); + public java.util.List getCitiesList() { + return cities_; + } + public int getCitiesCount() { return cities_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex getCities(int index) { + return cities_.get(index); + } + + // optional .OsmAndAddressNameIndexData nameIndex = 7; + public static final int NAMEINDEX_FIELD_NUMBER = 7; + private boolean hasNameIndex; + private net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData nameIndex_; + public boolean hasNameIndex() { return hasNameIndex; } + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData getNameIndex() { return nameIndex_; } + + private void initFields() { + boundaries_ = net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + nameIndex_ = net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + if (hasBoundaries()) { + if (!getBoundaries().isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex element : getCitiesList()) { + if (!element.isInitialized()) return false; + } + if (hasNameIndex()) { + if (!getNameIndex().isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasNameEn()) { + output.writeString(2, getNameEn()); + } + if (hasBoundaries()) { + output.writeMessage(3, getBoundaries()); + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex element : getCitiesList()) { + output.writeMessage(6, element); + } + if (hasNameIndex()) { + output.writeMessage(7, getNameIndex()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getNameEn()); + } + if (hasBoundaries()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getBoundaries()); + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex element : getCitiesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + if (hasNameIndex()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, getNameIndex()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndAddressIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndAddressIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndAddressIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndAddressIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndAddressIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndAddressIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndAddressIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.cities_ != java.util.Collections.EMPTY_LIST) { + result.cities_ = + java.util.Collections.unmodifiableList(result.cities_); + } + net.osmand.binary.OsmandOdb.OsmAndAddressIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndAddressIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndAddressIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndAddressIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndAddressIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasBoundaries()) { + mergeBoundaries(other.getBoundaries()); + } + if (!other.cities_.isEmpty()) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.addAll(other.cities_); + } + if (other.hasNameIndex()) { + mergeNameIndex(other.getNameIndex()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + setNameEn(input.readString()); + break; + } + case 26: { + net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder(); + if (hasBoundaries()) { + subBuilder.mergeFrom(getBoundaries()); + } + input.readMessage(subBuilder, extensionRegistry); + setBoundaries(subBuilder.buildPartial()); + break; + } + case 50: { + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addCities(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.newBuilder(); + if (hasNameIndex()) { + subBuilder.mergeFrom(getNameIndex()); + } + input.readMessage(subBuilder, extensionRegistry); + setNameIndex(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string name_en = 2; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // optional .OsmAndTileBox boundaries = 3; + public boolean hasBoundaries() { + return result.hasBoundaries(); + } + public net.osmand.binary.OsmandOdb.OsmAndTileBox getBoundaries() { + return result.getBoundaries(); + } + public Builder setBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasBoundaries = true; + result.boundaries_ = value; + return this; + } + public Builder setBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder builderForValue) { + result.hasBoundaries = true; + result.boundaries_ = builderForValue.build(); + return this; + } + public Builder mergeBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox value) { + if (result.hasBoundaries() && + result.boundaries_ != net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance()) { + result.boundaries_ = + net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder(result.boundaries_).mergeFrom(value).buildPartial(); + } else { + result.boundaries_ = value; + } + result.hasBoundaries = true; + return this; + } + public Builder clearBoundaries() { + result.hasBoundaries = false; + result.boundaries_ = net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + return this; + } + + // repeated .OsmAndAddressIndex.CitiesIndex cities = 6; + public java.util.List getCitiesList() { + return java.util.Collections.unmodifiableList(result.cities_); + } + public int getCitiesCount() { + return result.getCitiesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex getCities(int index) { + return result.getCities(index); + } + public Builder setCities(int index, net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.cities_.set(index, value); + return this; + } + public Builder setCities(int index, net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.Builder builderForValue) { + result.cities_.set(index, builderForValue.build()); + return this; + } + public Builder addCities(net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.add(value); + return this; + } + public Builder addCities(net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.Builder builderForValue) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + result.cities_.add(builderForValue.build()); + return this; + } + public Builder addAllCities( + java.lang.Iterable values) { + if (result.cities_.isEmpty()) { + result.cities_ = new java.util.ArrayList(); + } + super.addAll(values, result.cities_); + return this; + } + public Builder clearCities() { + result.cities_ = java.util.Collections.emptyList(); + return this; + } + + // optional .OsmAndAddressNameIndexData nameIndex = 7; + public boolean hasNameIndex() { + return result.hasNameIndex(); + } + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData getNameIndex() { + return result.getNameIndex(); + } + public Builder setNameIndex(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameIndex = true; + result.nameIndex_ = value; + return this; + } + public Builder setNameIndex(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.Builder builderForValue) { + result.hasNameIndex = true; + result.nameIndex_ = builderForValue.build(); + return this; + } + public Builder mergeNameIndex(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData value) { + if (result.hasNameIndex() && + result.nameIndex_ != net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.getDefaultInstance()) { + result.nameIndex_ = + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.newBuilder(result.nameIndex_).mergeFrom(value).buildPartial(); + } else { + result.nameIndex_ = value; + } + result.hasNameIndex = true; + return this; + } + public Builder clearNameIndex() { + result.hasNameIndex = false; + result.nameIndex_ = net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndAddressIndex) + } + + static { + defaultInstance = new OsmAndAddressIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndAddressIndex) + } + + public static final class OsmAndAddressNameIndexData extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndAddressNameIndexData.newBuilder() to construct. + private OsmAndAddressNameIndexData() { + initFields(); + } + private OsmAndAddressNameIndexData(boolean noInit) {} + + private static final OsmAndAddressNameIndexData defaultInstance; + public static OsmAndAddressNameIndexData getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndAddressNameIndexData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressNameIndexData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressNameIndexData_fieldAccessorTable; + } + + public static final class AddressNameIndexData extends + com.google.protobuf.GeneratedMessage { + // Use AddressNameIndexData.newBuilder() to construct. + private AddressNameIndexData() { + initFields(); + } + private AddressNameIndexData(boolean noInit) {} + + private static final AddressNameIndexData defaultInstance; + public static AddressNameIndexData getDefaultInstance() { + return defaultInstance; + } + + @Override + public AddressNameIndexData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_fieldAccessorTable; + } + + // repeated .AddressNameIndexDataAtom atom = 4; + public static final int ATOM_FIELD_NUMBER = 4; + private java.util.List atom_ = + java.util.Collections.emptyList(); + public java.util.List getAtomList() { + return atom_; + } + public int getAtomCount() { return atom_.size(); } + public net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom getAtom(int index) { + return atom_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + for (net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom element : getAtomList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom element : getAtomList()) { + output.writeMessage(4, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + for (net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom element : getAtomList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.atom_ != java.util.Collections.EMPTY_LIST) { + result.atom_ = + java.util.Collections.unmodifiableList(result.atom_); + } + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.getDefaultInstance()) return this; + if (!other.atom_.isEmpty()) { + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + result.atom_.addAll(other.atom_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 34: { + net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.Builder subBuilder = net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addAtom(subBuilder.buildPartial()); + break; + } + } + } + } + + + // repeated .AddressNameIndexDataAtom atom = 4; + public java.util.List getAtomList() { + return java.util.Collections.unmodifiableList(result.atom_); + } + public int getAtomCount() { + return result.getAtomCount(); + } + public net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom getAtom(int index) { + return result.getAtom(index); + } + public Builder setAtom(int index, net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom value) { + if (value == null) { + throw new NullPointerException(); + } + result.atom_.set(index, value); + return this; + } + public Builder setAtom(int index, net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.Builder builderForValue) { + result.atom_.set(index, builderForValue.build()); + return this; + } + public Builder addAtom(net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + result.atom_.add(value); + return this; + } + public Builder addAtom(net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.Builder builderForValue) { + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + result.atom_.add(builderForValue.build()); + return this; + } + public Builder addAllAtom( + java.lang.Iterable values) { + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + super.addAll(values, result.atom_); + return this; + } + public Builder clearAtom() { + result.atom_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndAddressNameIndexData.AddressNameIndexData) + } + + static { + defaultInstance = new AddressNameIndexData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndAddressNameIndexData.AddressNameIndexData) + } + + // required .IndexedStringTable table = 4; + public static final int TABLE_FIELD_NUMBER = 4; + private boolean hasTable; + private net.osmand.binary.OsmandOdb.IndexedStringTable table_; + public boolean hasTable() { return hasTable; } + public net.osmand.binary.OsmandOdb.IndexedStringTable getTable() { return table_; } + + // repeated .OsmAndAddressNameIndexData.AddressNameIndexData atom = 7; + public static final int ATOM_FIELD_NUMBER = 7; + private java.util.List atom_ = + java.util.Collections.emptyList(); + public java.util.List getAtomList() { + return atom_; + } + public int getAtomCount() { return atom_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData getAtom(int index) { + return atom_.get(index); + } + + private void initFields() { + table_ = net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasTable) return false; + for (net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData element : getAtomList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasTable()) { + output.writeMessage(4, getTable()); + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData element : getAtomList()) { + output.writeMessage(7, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasTable()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getTable()); + } + for (net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData element : getAtomList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.atom_ != java.util.Collections.EMPTY_LIST) { + result.atom_ = + java.util.Collections.unmodifiableList(result.atom_); + } + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.getDefaultInstance()) return this; + if (other.hasTable()) { + mergeTable(other.getTable()); + } + if (!other.atom_.isEmpty()) { + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + result.atom_.addAll(other.atom_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 34: { + net.osmand.binary.OsmandOdb.IndexedStringTable.Builder subBuilder = net.osmand.binary.OsmandOdb.IndexedStringTable.newBuilder(); + if (hasTable()) { + subBuilder.mergeFrom(getTable()); + } + input.readMessage(subBuilder, extensionRegistry); + setTable(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addAtom(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required .IndexedStringTable table = 4; + public boolean hasTable() { + return result.hasTable(); + } + public net.osmand.binary.OsmandOdb.IndexedStringTable getTable() { + return result.getTable(); + } + public Builder setTable(net.osmand.binary.OsmandOdb.IndexedStringTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTable = true; + result.table_ = value; + return this; + } + public Builder setTable(net.osmand.binary.OsmandOdb.IndexedStringTable.Builder builderForValue) { + result.hasTable = true; + result.table_ = builderForValue.build(); + return this; + } + public Builder mergeTable(net.osmand.binary.OsmandOdb.IndexedStringTable value) { + if (result.hasTable() && + result.table_ != net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance()) { + result.table_ = + net.osmand.binary.OsmandOdb.IndexedStringTable.newBuilder(result.table_).mergeFrom(value).buildPartial(); + } else { + result.table_ = value; + } + result.hasTable = true; + return this; + } + public Builder clearTable() { + result.hasTable = false; + result.table_ = net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance(); + return this; + } + + // repeated .OsmAndAddressNameIndexData.AddressNameIndexData atom = 7; + public java.util.List getAtomList() { + return java.util.Collections.unmodifiableList(result.atom_); + } + public int getAtomCount() { + return result.getAtomCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData getAtom(int index) { + return result.getAtom(index); + } + public Builder setAtom(int index, net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData value) { + if (value == null) { + throw new NullPointerException(); + } + result.atom_.set(index, value); + return this; + } + public Builder setAtom(int index, net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.Builder builderForValue) { + result.atom_.set(index, builderForValue.build()); + return this; + } + public Builder addAtom(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + result.atom_.add(value); + return this; + } + public Builder addAtom(net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.Builder builderForValue) { + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + result.atom_.add(builderForValue.build()); + return this; + } + public Builder addAllAtom( + java.lang.Iterable values) { + if (result.atom_.isEmpty()) { + result.atom_ = new java.util.ArrayList(); + } + super.addAll(values, result.atom_); + return this; + } + public Builder clearAtom() { + result.atom_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndAddressNameIndexData) + } + + static { + defaultInstance = new OsmAndAddressNameIndexData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndAddressNameIndexData) + } + + public static final class AddressNameIndexDataAtom extends + com.google.protobuf.GeneratedMessage { + // Use AddressNameIndexDataAtom.newBuilder() to construct. + private AddressNameIndexDataAtom() { + initFields(); + } + private AddressNameIndexDataAtom(boolean noInit) {} + + private static final AddressNameIndexDataAtom defaultInstance; + public static AddressNameIndexDataAtom getDefaultInstance() { + return defaultInstance; + } + + @Override + public AddressNameIndexDataAtom getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_AddressNameIndexDataAtom_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_AddressNameIndexDataAtom_fieldAccessorTable; + } + + // optional string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string nameEn = 2; + public static final int NAMEEN_FIELD_NUMBER = 2; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // required uint32 type = 3; + public static final int TYPE_FIELD_NUMBER = 3; + private boolean hasType; + private int type_ = 0; + public boolean hasType() { return hasType; } + public int getType() { return type_; } + + // repeated int32 shiftToIndex = 5; + public static final int SHIFTTOINDEX_FIELD_NUMBER = 5; + private java.util.List shiftToIndex_ = + java.util.Collections.emptyList(); + public java.util.List getShiftToIndexList() { + return shiftToIndex_; + } + public int getShiftToIndexCount() { return shiftToIndex_.size(); } + public int getShiftToIndex(int index) { + return shiftToIndex_.get(index); + } + + // repeated int32 shiftToCityIndex = 6; + public static final int SHIFTTOCITYINDEX_FIELD_NUMBER = 6; + private java.util.List shiftToCityIndex_ = + java.util.Collections.emptyList(); + public java.util.List getShiftToCityIndexList() { + return shiftToCityIndex_; + } + public int getShiftToCityIndexCount() { return shiftToCityIndex_.size(); } + public int getShiftToCityIndex(int index) { + return shiftToCityIndex_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasType) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasNameEn()) { + output.writeString(2, getNameEn()); + } + if (hasType()) { + output.writeUInt32(3, getType()); + } + for (int element : getShiftToIndexList()) { + output.writeInt32(5, element); + } + for (int element : getShiftToCityIndexList()) { + output.writeInt32(6, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getNameEn()); + } + if (hasType()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(3, getType()); + } + { + int dataSize = 0; + for (int element : getShiftToIndexList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(element); + } + size += dataSize; + size += 1 * getShiftToIndexList().size(); + } + { + int dataSize = 0; + for (int element : getShiftToCityIndexList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(element); + } + size += dataSize; + size += 1 * getShiftToCityIndexList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom result; + + // Construct using net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.shiftToIndex_ != java.util.Collections.EMPTY_LIST) { + result.shiftToIndex_ = + java.util.Collections.unmodifiableList(result.shiftToIndex_); + } + if (result.shiftToCityIndex_ != java.util.Collections.EMPTY_LIST) { + result.shiftToCityIndex_ = + java.util.Collections.unmodifiableList(result.shiftToCityIndex_); + } + net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom) { + return mergeFrom((net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom other) { + if (other == net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasType()) { + setType(other.getType()); + } + if (!other.shiftToIndex_.isEmpty()) { + if (result.shiftToIndex_.isEmpty()) { + result.shiftToIndex_ = new java.util.ArrayList(); + } + result.shiftToIndex_.addAll(other.shiftToIndex_); + } + if (!other.shiftToCityIndex_.isEmpty()) { + if (result.shiftToCityIndex_.isEmpty()) { + result.shiftToCityIndex_ = new java.util.ArrayList(); + } + result.shiftToCityIndex_.addAll(other.shiftToCityIndex_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + setNameEn(input.readString()); + break; + } + case 24: { + setType(input.readUInt32()); + break; + } + case 40: { + addShiftToIndex(input.readInt32()); + break; + } + case 42: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addShiftToIndex(input.readInt32()); + } + input.popLimit(limit); + break; + } + case 48: { + addShiftToCityIndex(input.readInt32()); + break; + } + case 50: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addShiftToCityIndex(input.readInt32()); + } + input.popLimit(limit); + break; + } + } + } + } + + + // optional string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string nameEn = 2; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // required uint32 type = 3; + public boolean hasType() { + return result.hasType(); + } + public int getType() { + return result.getType(); + } + public Builder setType(int value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder clearType() { + result.hasType = false; + result.type_ = 0; + return this; + } + + // repeated int32 shiftToIndex = 5; + public java.util.List getShiftToIndexList() { + return java.util.Collections.unmodifiableList(result.shiftToIndex_); + } + public int getShiftToIndexCount() { + return result.getShiftToIndexCount(); + } + public int getShiftToIndex(int index) { + return result.getShiftToIndex(index); + } + public Builder setShiftToIndex(int index, int value) { + result.shiftToIndex_.set(index, value); + return this; + } + public Builder addShiftToIndex(int value) { + if (result.shiftToIndex_.isEmpty()) { + result.shiftToIndex_ = new java.util.ArrayList(); + } + result.shiftToIndex_.add(value); + return this; + } + public Builder addAllShiftToIndex( + java.lang.Iterable values) { + if (result.shiftToIndex_.isEmpty()) { + result.shiftToIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.shiftToIndex_); + return this; + } + public Builder clearShiftToIndex() { + result.shiftToIndex_ = java.util.Collections.emptyList(); + return this; + } + + // repeated int32 shiftToCityIndex = 6; + public java.util.List getShiftToCityIndexList() { + return java.util.Collections.unmodifiableList(result.shiftToCityIndex_); + } + public int getShiftToCityIndexCount() { + return result.getShiftToCityIndexCount(); + } + public int getShiftToCityIndex(int index) { + return result.getShiftToCityIndex(index); + } + public Builder setShiftToCityIndex(int index, int value) { + result.shiftToCityIndex_.set(index, value); + return this; + } + public Builder addShiftToCityIndex(int value) { + if (result.shiftToCityIndex_.isEmpty()) { + result.shiftToCityIndex_ = new java.util.ArrayList(); + } + result.shiftToCityIndex_.add(value); + return this; + } + public Builder addAllShiftToCityIndex( + java.lang.Iterable values) { + if (result.shiftToCityIndex_.isEmpty()) { + result.shiftToCityIndex_ = new java.util.ArrayList(); + } + super.addAll(values, result.shiftToCityIndex_); + return this; + } + public Builder clearShiftToCityIndex() { + result.shiftToCityIndex_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:AddressNameIndexDataAtom) + } + + static { + defaultInstance = new AddressNameIndexDataAtom(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:AddressNameIndexDataAtom) + } + + public static final class CityIndex extends + com.google.protobuf.GeneratedMessage { + // Use CityIndex.newBuilder() to construct. + private CityIndex() { + initFields(); + } + private CityIndex(boolean noInit) {} + + private static final CityIndex defaultInstance; + public static CityIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public CityIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_CityIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_CityIndex_fieldAccessorTable; + } + + // optional uint32 city_type = 1; + public static final int CITY_TYPE_FIELD_NUMBER = 1; + private boolean hasCityType; + private int cityType_ = 0; + public boolean hasCityType() { return hasCityType; } + public int getCityType() { return cityType_; } + + // required string name = 2; + public static final int NAME_FIELD_NUMBER = 2; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string name_en = 3; + public static final int NAME_EN_FIELD_NUMBER = 3; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // optional uint64 id = 4; + public static final int ID_FIELD_NUMBER = 4; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // required uint32 x = 5; + public static final int X_FIELD_NUMBER = 5; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // required uint32 y = 6; + public static final int Y_FIELD_NUMBER = 6; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // optional fixed32 shiftToCityBlockIndex = 10; + public static final int SHIFTTOCITYBLOCKINDEX_FIELD_NUMBER = 10; + private boolean hasShiftToCityBlockIndex; + private int shiftToCityBlockIndex_ = 0; + public boolean hasShiftToCityBlockIndex() { return hasShiftToCityBlockIndex; } + public int getShiftToCityBlockIndex() { return shiftToCityBlockIndex_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + if (!hasX) return false; + if (!hasY) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasCityType()) { + output.writeUInt32(1, getCityType()); + } + if (hasName()) { + output.writeString(2, getName()); + } + if (hasNameEn()) { + output.writeString(3, getNameEn()); + } + if (hasId()) { + output.writeUInt64(4, getId()); + } + if (hasX()) { + output.writeUInt32(5, getX()); + } + if (hasY()) { + output.writeUInt32(6, getY()); + } + if (hasShiftToCityBlockIndex()) { + output.writeFixed32(10, getShiftToCityBlockIndex()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasCityType()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, getCityType()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getNameEn()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(4, getId()); + } + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(5, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(6, getY()); + } + if (hasShiftToCityBlockIndex()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(10, getShiftToCityBlockIndex()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.CityIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.CityIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.CityIndex result; + + // Construct using net.osmand.binary.OsmandOdb.CityIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.CityIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.CityIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.CityIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.CityIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.CityIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.CityIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.CityIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.CityIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.CityIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.CityIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.CityIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.CityIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.CityIndex other) { + if (other == net.osmand.binary.OsmandOdb.CityIndex.getDefaultInstance()) return this; + if (other.hasCityType()) { + setCityType(other.getCityType()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (other.hasShiftToCityBlockIndex()) { + setShiftToCityBlockIndex(other.getShiftToCityBlockIndex()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setCityType(input.readUInt32()); + break; + } + case 18: { + setName(input.readString()); + break; + } + case 26: { + setNameEn(input.readString()); + break; + } + case 32: { + setId(input.readUInt64()); + break; + } + case 40: { + setX(input.readUInt32()); + break; + } + case 48: { + setY(input.readUInt32()); + break; + } + case 85: { + setShiftToCityBlockIndex(input.readFixed32()); + break; + } + } + } + } + + + // optional uint32 city_type = 1; + public boolean hasCityType() { + return result.hasCityType(); + } + public int getCityType() { + return result.getCityType(); + } + public Builder setCityType(int value) { + result.hasCityType = true; + result.cityType_ = value; + return this; + } + public Builder clearCityType() { + result.hasCityType = false; + result.cityType_ = 0; + return this; + } + + // required string name = 2; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string name_en = 3; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // optional uint64 id = 4; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // required uint32 x = 5; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // required uint32 y = 6; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // optional fixed32 shiftToCityBlockIndex = 10; + public boolean hasShiftToCityBlockIndex() { + return result.hasShiftToCityBlockIndex(); + } + public int getShiftToCityBlockIndex() { + return result.getShiftToCityBlockIndex(); + } + public Builder setShiftToCityBlockIndex(int value) { + result.hasShiftToCityBlockIndex = true; + result.shiftToCityBlockIndex_ = value; + return this; + } + public Builder clearShiftToCityBlockIndex() { + result.hasShiftToCityBlockIndex = false; + result.shiftToCityBlockIndex_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:CityIndex) + } + + static { + defaultInstance = new CityIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:CityIndex) + } + + public static final class CityBlockIndex extends + com.google.protobuf.GeneratedMessage { + // Use CityBlockIndex.newBuilder() to construct. + private CityBlockIndex() { + initFields(); + } + private CityBlockIndex(boolean noInit) {} + + private static final CityBlockIndex defaultInstance; + public static CityBlockIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public CityBlockIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_CityBlockIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_CityBlockIndex_fieldAccessorTable; + } + + // optional fixed32 shiftToCityIndex = 4; + public static final int SHIFTTOCITYINDEX_FIELD_NUMBER = 4; + private boolean hasShiftToCityIndex; + private int shiftToCityIndex_ = 0; + public boolean hasShiftToCityIndex() { return hasShiftToCityIndex; } + public int getShiftToCityIndex() { return shiftToCityIndex_; } + + // repeated .BuildingIndex buildings = 10; + public static final int BUILDINGS_FIELD_NUMBER = 10; + private java.util.List buildings_ = + java.util.Collections.emptyList(); + public java.util.List getBuildingsList() { + return buildings_; + } + public int getBuildingsCount() { return buildings_.size(); } + public net.osmand.binary.OsmandOdb.BuildingIndex getBuildings(int index) { + return buildings_.get(index); + } + + // repeated .StreetIndex streets = 12; + public static final int STREETS_FIELD_NUMBER = 12; + private java.util.List streets_ = + java.util.Collections.emptyList(); + public java.util.List getStreetsList() { + return streets_; + } + public int getStreetsCount() { return streets_.size(); } + public net.osmand.binary.OsmandOdb.StreetIndex getStreets(int index) { + return streets_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasShiftToCityIndex()) { + output.writeFixed32(4, getShiftToCityIndex()); + } + for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) { + output.writeMessage(10, element); + } + for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) { + output.writeMessage(12, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasShiftToCityIndex()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(4, getShiftToCityIndex()); + } + for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(10, element); + } + for (net.osmand.binary.OsmandOdb.StreetIndex element : getStreetsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(12, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.CityBlockIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.CityBlockIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.CityBlockIndex result; + + // Construct using net.osmand.binary.OsmandOdb.CityBlockIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.CityBlockIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.CityBlockIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.CityBlockIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.CityBlockIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.CityBlockIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.CityBlockIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.CityBlockIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.CityBlockIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.CityBlockIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.buildings_ != java.util.Collections.EMPTY_LIST) { + result.buildings_ = + java.util.Collections.unmodifiableList(result.buildings_); + } + if (result.streets_ != java.util.Collections.EMPTY_LIST) { + result.streets_ = + java.util.Collections.unmodifiableList(result.streets_); + } + net.osmand.binary.OsmandOdb.CityBlockIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.CityBlockIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.CityBlockIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.CityBlockIndex other) { + if (other == net.osmand.binary.OsmandOdb.CityBlockIndex.getDefaultInstance()) return this; + if (other.hasShiftToCityIndex()) { + setShiftToCityIndex(other.getShiftToCityIndex()); + } + if (!other.buildings_.isEmpty()) { + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + result.buildings_.addAll(other.buildings_); + } + if (!other.streets_.isEmpty()) { + if (result.streets_.isEmpty()) { + result.streets_ = new java.util.ArrayList(); + } + result.streets_.addAll(other.streets_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 37: { + setShiftToCityIndex(input.readFixed32()); + break; + } + case 82: { + net.osmand.binary.OsmandOdb.BuildingIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.BuildingIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBuildings(subBuilder.buildPartial()); + break; + } + case 98: { + net.osmand.binary.OsmandOdb.StreetIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.StreetIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addStreets(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional fixed32 shiftToCityIndex = 4; + public boolean hasShiftToCityIndex() { + return result.hasShiftToCityIndex(); + } + public int getShiftToCityIndex() { + return result.getShiftToCityIndex(); + } + public Builder setShiftToCityIndex(int value) { + result.hasShiftToCityIndex = true; + result.shiftToCityIndex_ = value; + return this; + } + public Builder clearShiftToCityIndex() { + result.hasShiftToCityIndex = false; + result.shiftToCityIndex_ = 0; + return this; + } + + // repeated .BuildingIndex buildings = 10; + public java.util.List getBuildingsList() { + return java.util.Collections.unmodifiableList(result.buildings_); + } + public int getBuildingsCount() { + return result.getBuildingsCount(); + } + public net.osmand.binary.OsmandOdb.BuildingIndex getBuildings(int index) { + return result.getBuildings(index); + } + public Builder setBuildings(int index, net.osmand.binary.OsmandOdb.BuildingIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.buildings_.set(index, value); + return this; + } + public Builder setBuildings(int index, net.osmand.binary.OsmandOdb.BuildingIndex.Builder builderForValue) { + result.buildings_.set(index, builderForValue.build()); + return this; + } + public Builder addBuildings(net.osmand.binary.OsmandOdb.BuildingIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + result.buildings_.add(value); + return this; + } + public Builder addBuildings(net.osmand.binary.OsmandOdb.BuildingIndex.Builder builderForValue) { + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + result.buildings_.add(builderForValue.build()); + return this; + } + public Builder addAllBuildings( + java.lang.Iterable values) { + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + super.addAll(values, result.buildings_); + return this; + } + public Builder clearBuildings() { + result.buildings_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .StreetIndex streets = 12; + public java.util.List getStreetsList() { + return java.util.Collections.unmodifiableList(result.streets_); + } + public int getStreetsCount() { + return result.getStreetsCount(); + } + public net.osmand.binary.OsmandOdb.StreetIndex getStreets(int index) { + return result.getStreets(index); + } + public Builder setStreets(int index, net.osmand.binary.OsmandOdb.StreetIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.streets_.set(index, value); + return this; + } + public Builder setStreets(int index, net.osmand.binary.OsmandOdb.StreetIndex.Builder builderForValue) { + result.streets_.set(index, builderForValue.build()); + return this; + } + public Builder addStreets(net.osmand.binary.OsmandOdb.StreetIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.streets_.isEmpty()) { + result.streets_ = new java.util.ArrayList(); + } + result.streets_.add(value); + return this; + } + public Builder addStreets(net.osmand.binary.OsmandOdb.StreetIndex.Builder builderForValue) { + if (result.streets_.isEmpty()) { + result.streets_ = new java.util.ArrayList(); + } + result.streets_.add(builderForValue.build()); + return this; + } + public Builder addAllStreets( + java.lang.Iterable values) { + if (result.streets_.isEmpty()) { + result.streets_ = new java.util.ArrayList(); + } + super.addAll(values, result.streets_); + return this; + } + public Builder clearStreets() { + result.streets_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:CityBlockIndex) + } + + static { + defaultInstance = new CityBlockIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:CityBlockIndex) + } + + public static final class StreetIndex extends + com.google.protobuf.GeneratedMessage { + // Use StreetIndex.newBuilder() to construct. + private StreetIndex() { + initFields(); + } + private StreetIndex(boolean noInit) {} + + private static final StreetIndex defaultInstance; + public static StreetIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public StreetIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_StreetIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_StreetIndex_fieldAccessorTable; + } + + // required string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string name_en = 2; + public static final int NAME_EN_FIELD_NUMBER = 2; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // required sint32 x = 3; + public static final int X_FIELD_NUMBER = 3; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // required sint32 y = 4; + public static final int Y_FIELD_NUMBER = 4; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // optional uint64 id = 6; + public static final int ID_FIELD_NUMBER = 6; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // repeated .BuildingIndex buildings = 12; + public static final int BUILDINGS_FIELD_NUMBER = 12; + private java.util.List buildings_ = + java.util.Collections.emptyList(); + public java.util.List getBuildingsList() { + return buildings_; + } + public int getBuildingsCount() { return buildings_.size(); } + public net.osmand.binary.OsmandOdb.BuildingIndex getBuildings(int index) { + return buildings_.get(index); + } + + // repeated .StreetIntersection intersections = 5; + public static final int INTERSECTIONS_FIELD_NUMBER = 5; + private java.util.List intersections_ = + java.util.Collections.emptyList(); + public java.util.List getIntersectionsList() { + return intersections_; + } + public int getIntersectionsCount() { return intersections_.size(); } + public net.osmand.binary.OsmandOdb.StreetIntersection getIntersections(int index) { + return intersections_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + if (!hasX) return false; + if (!hasY) return false; + for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.StreetIntersection element : getIntersectionsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasNameEn()) { + output.writeString(2, getNameEn()); + } + if (hasX()) { + output.writeSInt32(3, getX()); + } + if (hasY()) { + output.writeSInt32(4, getY()); + } + for (net.osmand.binary.OsmandOdb.StreetIntersection element : getIntersectionsList()) { + output.writeMessage(5, element); + } + if (hasId()) { + output.writeUInt64(6, getId()); + } + for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) { + output.writeMessage(12, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getNameEn()); + } + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(4, getY()); + } + for (net.osmand.binary.OsmandOdb.StreetIntersection element : getIntersectionsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(6, getId()); + } + for (net.osmand.binary.OsmandOdb.BuildingIndex element : getBuildingsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(12, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.StreetIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.StreetIndex result; + + // Construct using net.osmand.binary.OsmandOdb.StreetIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.StreetIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.StreetIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.StreetIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.StreetIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.StreetIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.StreetIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.StreetIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.StreetIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.StreetIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.buildings_ != java.util.Collections.EMPTY_LIST) { + result.buildings_ = + java.util.Collections.unmodifiableList(result.buildings_); + } + if (result.intersections_ != java.util.Collections.EMPTY_LIST) { + result.intersections_ = + java.util.Collections.unmodifiableList(result.intersections_); + } + net.osmand.binary.OsmandOdb.StreetIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.StreetIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.StreetIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.StreetIndex other) { + if (other == net.osmand.binary.OsmandOdb.StreetIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (!other.buildings_.isEmpty()) { + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + result.buildings_.addAll(other.buildings_); + } + if (!other.intersections_.isEmpty()) { + if (result.intersections_.isEmpty()) { + result.intersections_ = new java.util.ArrayList(); + } + result.intersections_.addAll(other.intersections_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + setNameEn(input.readString()); + break; + } + case 24: { + setX(input.readSInt32()); + break; + } + case 32: { + setY(input.readSInt32()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.StreetIntersection.Builder subBuilder = net.osmand.binary.OsmandOdb.StreetIntersection.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addIntersections(subBuilder.buildPartial()); + break; + } + case 48: { + setId(input.readUInt64()); + break; + } + case 98: { + net.osmand.binary.OsmandOdb.BuildingIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.BuildingIndex.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBuildings(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string name_en = 2; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // required sint32 x = 3; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // required sint32 y = 4; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // optional uint64 id = 6; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // repeated .BuildingIndex buildings = 12; + public java.util.List getBuildingsList() { + return java.util.Collections.unmodifiableList(result.buildings_); + } + public int getBuildingsCount() { + return result.getBuildingsCount(); + } + public net.osmand.binary.OsmandOdb.BuildingIndex getBuildings(int index) { + return result.getBuildings(index); + } + public Builder setBuildings(int index, net.osmand.binary.OsmandOdb.BuildingIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.buildings_.set(index, value); + return this; + } + public Builder setBuildings(int index, net.osmand.binary.OsmandOdb.BuildingIndex.Builder builderForValue) { + result.buildings_.set(index, builderForValue.build()); + return this; + } + public Builder addBuildings(net.osmand.binary.OsmandOdb.BuildingIndex value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + result.buildings_.add(value); + return this; + } + public Builder addBuildings(net.osmand.binary.OsmandOdb.BuildingIndex.Builder builderForValue) { + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + result.buildings_.add(builderForValue.build()); + return this; + } + public Builder addAllBuildings( + java.lang.Iterable values) { + if (result.buildings_.isEmpty()) { + result.buildings_ = new java.util.ArrayList(); + } + super.addAll(values, result.buildings_); + return this; + } + public Builder clearBuildings() { + result.buildings_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .StreetIntersection intersections = 5; + public java.util.List getIntersectionsList() { + return java.util.Collections.unmodifiableList(result.intersections_); + } + public int getIntersectionsCount() { + return result.getIntersectionsCount(); + } + public net.osmand.binary.OsmandOdb.StreetIntersection getIntersections(int index) { + return result.getIntersections(index); + } + public Builder setIntersections(int index, net.osmand.binary.OsmandOdb.StreetIntersection value) { + if (value == null) { + throw new NullPointerException(); + } + result.intersections_.set(index, value); + return this; + } + public Builder setIntersections(int index, net.osmand.binary.OsmandOdb.StreetIntersection.Builder builderForValue) { + result.intersections_.set(index, builderForValue.build()); + return this; + } + public Builder addIntersections(net.osmand.binary.OsmandOdb.StreetIntersection value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.intersections_.isEmpty()) { + result.intersections_ = new java.util.ArrayList(); + } + result.intersections_.add(value); + return this; + } + public Builder addIntersections(net.osmand.binary.OsmandOdb.StreetIntersection.Builder builderForValue) { + if (result.intersections_.isEmpty()) { + result.intersections_ = new java.util.ArrayList(); + } + result.intersections_.add(builderForValue.build()); + return this; + } + public Builder addAllIntersections( + java.lang.Iterable values) { + if (result.intersections_.isEmpty()) { + result.intersections_ = new java.util.ArrayList(); + } + super.addAll(values, result.intersections_); + return this; + } + public Builder clearIntersections() { + result.intersections_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:StreetIndex) + } + + static { + defaultInstance = new StreetIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:StreetIndex) + } + + public static final class StreetIntersection extends + com.google.protobuf.GeneratedMessage { + // Use StreetIntersection.newBuilder() to construct. + private StreetIntersection() { + initFields(); + } + private StreetIntersection(boolean noInit) {} + + private static final StreetIntersection defaultInstance; + public static StreetIntersection getDefaultInstance() { + return defaultInstance; + } + + @Override + public StreetIntersection getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_StreetIntersection_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_StreetIntersection_fieldAccessorTable; + } + + // required string name = 2; + public static final int NAME_FIELD_NUMBER = 2; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string name_en = 3; + public static final int NAME_EN_FIELD_NUMBER = 3; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // required sint32 intersectedX = 4; + public static final int INTERSECTEDX_FIELD_NUMBER = 4; + private boolean hasIntersectedX; + private int intersectedX_ = 0; + public boolean hasIntersectedX() { return hasIntersectedX; } + public int getIntersectedX() { return intersectedX_; } + + // required sint32 intersectedY = 5; + public static final int INTERSECTEDY_FIELD_NUMBER = 5; + private boolean hasIntersectedY; + private int intersectedY_ = 0; + public boolean hasIntersectedY() { return hasIntersectedY; } + public int getIntersectedY() { return intersectedY_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + if (!hasIntersectedX) return false; + if (!hasIntersectedY) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(2, getName()); + } + if (hasNameEn()) { + output.writeString(3, getNameEn()); + } + if (hasIntersectedX()) { + output.writeSInt32(4, getIntersectedX()); + } + if (hasIntersectedY()) { + output.writeSInt32(5, getIntersectedY()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getNameEn()); + } + if (hasIntersectedX()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(4, getIntersectedX()); + } + if (hasIntersectedY()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(5, getIntersectedY()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.StreetIntersection parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.StreetIntersection prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.StreetIntersection result; + + // Construct using net.osmand.binary.OsmandOdb.StreetIntersection.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.StreetIntersection(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.StreetIntersection internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.StreetIntersection(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.StreetIntersection.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.StreetIntersection getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.StreetIntersection.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.StreetIntersection build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.StreetIntersection buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.StreetIntersection buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.StreetIntersection returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.StreetIntersection) { + return mergeFrom((net.osmand.binary.OsmandOdb.StreetIntersection)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.StreetIntersection other) { + if (other == net.osmand.binary.OsmandOdb.StreetIntersection.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasIntersectedX()) { + setIntersectedX(other.getIntersectedX()); + } + if (other.hasIntersectedY()) { + setIntersectedY(other.getIntersectedY()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 18: { + setName(input.readString()); + break; + } + case 26: { + setNameEn(input.readString()); + break; + } + case 32: { + setIntersectedX(input.readSInt32()); + break; + } + case 40: { + setIntersectedY(input.readSInt32()); + break; + } + } + } + } + + + // required string name = 2; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string name_en = 3; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // required sint32 intersectedX = 4; + public boolean hasIntersectedX() { + return result.hasIntersectedX(); + } + public int getIntersectedX() { + return result.getIntersectedX(); + } + public Builder setIntersectedX(int value) { + result.hasIntersectedX = true; + result.intersectedX_ = value; + return this; + } + public Builder clearIntersectedX() { + result.hasIntersectedX = false; + result.intersectedX_ = 0; + return this; + } + + // required sint32 intersectedY = 5; + public boolean hasIntersectedY() { + return result.hasIntersectedY(); + } + public int getIntersectedY() { + return result.getIntersectedY(); + } + public Builder setIntersectedY(int value) { + result.hasIntersectedY = true; + result.intersectedY_ = value; + return this; + } + public Builder clearIntersectedY() { + result.hasIntersectedY = false; + result.intersectedY_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:StreetIntersection) + } + + static { + defaultInstance = new StreetIntersection(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:StreetIntersection) + } + + public static final class BuildingIndex extends + com.google.protobuf.GeneratedMessage { + // Use BuildingIndex.newBuilder() to construct. + private BuildingIndex() { + initFields(); + } + private BuildingIndex(boolean noInit) {} + + private static final BuildingIndex defaultInstance; + public static BuildingIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public BuildingIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_BuildingIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_BuildingIndex_fieldAccessorTable; + } + + // required string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string name_en = 2; + public static final int NAME_EN_FIELD_NUMBER = 2; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // optional string name2 = 3; + public static final int NAME2_FIELD_NUMBER = 3; + private boolean hasName2; + private java.lang.String name2_ = ""; + public boolean hasName2() { return hasName2; } + public java.lang.String getName2() { return name2_; } + + // optional string name_en2 = 4; + public static final int NAME_EN2_FIELD_NUMBER = 4; + private boolean hasNameEn2; + private java.lang.String nameEn2_ = ""; + public boolean hasNameEn2() { return hasNameEn2; } + public java.lang.String getNameEn2() { return nameEn2_; } + + // optional sint32 interpolation = 5; + public static final int INTERPOLATION_FIELD_NUMBER = 5; + private boolean hasInterpolation; + private int interpolation_ = 0; + public boolean hasInterpolation() { return hasInterpolation; } + public int getInterpolation() { return interpolation_; } + + // required sint32 x = 7; + public static final int X_FIELD_NUMBER = 7; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // required sint32 y = 8; + public static final int Y_FIELD_NUMBER = 8; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // optional sint32 x2 = 9; + public static final int X2_FIELD_NUMBER = 9; + private boolean hasX2; + private int x2_ = 0; + public boolean hasX2() { return hasX2; } + public int getX2() { return x2_; } + + // optional sint32 y2 = 10; + public static final int Y2_FIELD_NUMBER = 10; + private boolean hasY2; + private int y2_ = 0; + public boolean hasY2() { return hasY2; } + public int getY2() { return y2_; } + + // optional uint64 id = 13; + public static final int ID_FIELD_NUMBER = 13; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // optional string postcode = 14; + public static final int POSTCODE_FIELD_NUMBER = 14; + private boolean hasPostcode; + private java.lang.String postcode_ = ""; + public boolean hasPostcode() { return hasPostcode; } + public java.lang.String getPostcode() { return postcode_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + if (!hasX) return false; + if (!hasY) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasNameEn()) { + output.writeString(2, getNameEn()); + } + if (hasName2()) { + output.writeString(3, getName2()); + } + if (hasNameEn2()) { + output.writeString(4, getNameEn2()); + } + if (hasInterpolation()) { + output.writeSInt32(5, getInterpolation()); + } + if (hasX()) { + output.writeSInt32(7, getX()); + } + if (hasY()) { + output.writeSInt32(8, getY()); + } + if (hasX2()) { + output.writeSInt32(9, getX2()); + } + if (hasY2()) { + output.writeSInt32(10, getY2()); + } + if (hasId()) { + output.writeUInt64(13, getId()); + } + if (hasPostcode()) { + output.writeString(14, getPostcode()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getNameEn()); + } + if (hasName2()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getName2()); + } + if (hasNameEn2()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(4, getNameEn2()); + } + if (hasInterpolation()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(5, getInterpolation()); + } + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(7, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(8, getY()); + } + if (hasX2()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(9, getX2()); + } + if (hasY2()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(10, getY2()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(13, getId()); + } + if (hasPostcode()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(14, getPostcode()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.BuildingIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.BuildingIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.BuildingIndex result; + + // Construct using net.osmand.binary.OsmandOdb.BuildingIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.BuildingIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.BuildingIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.BuildingIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.BuildingIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.BuildingIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.BuildingIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.BuildingIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.BuildingIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.BuildingIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.BuildingIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.BuildingIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.BuildingIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.BuildingIndex other) { + if (other == net.osmand.binary.OsmandOdb.BuildingIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasName2()) { + setName2(other.getName2()); + } + if (other.hasNameEn2()) { + setNameEn2(other.getNameEn2()); + } + if (other.hasInterpolation()) { + setInterpolation(other.getInterpolation()); + } + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (other.hasX2()) { + setX2(other.getX2()); + } + if (other.hasY2()) { + setY2(other.getY2()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasPostcode()) { + setPostcode(other.getPostcode()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + setNameEn(input.readString()); + break; + } + case 26: { + setName2(input.readString()); + break; + } + case 34: { + setNameEn2(input.readString()); + break; + } + case 40: { + setInterpolation(input.readSInt32()); + break; + } + case 56: { + setX(input.readSInt32()); + break; + } + case 64: { + setY(input.readSInt32()); + break; + } + case 72: { + setX2(input.readSInt32()); + break; + } + case 80: { + setY2(input.readSInt32()); + break; + } + case 104: { + setId(input.readUInt64()); + break; + } + case 114: { + setPostcode(input.readString()); + break; + } + } + } + } + + + // required string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string name_en = 2; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // optional string name2 = 3; + public boolean hasName2() { + return result.hasName2(); + } + public java.lang.String getName2() { + return result.getName2(); + } + public Builder setName2(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName2 = true; + result.name2_ = value; + return this; + } + public Builder clearName2() { + result.hasName2 = false; + result.name2_ = getDefaultInstance().getName2(); + return this; + } + + // optional string name_en2 = 4; + public boolean hasNameEn2() { + return result.hasNameEn2(); + } + public java.lang.String getNameEn2() { + return result.getNameEn2(); + } + public Builder setNameEn2(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn2 = true; + result.nameEn2_ = value; + return this; + } + public Builder clearNameEn2() { + result.hasNameEn2 = false; + result.nameEn2_ = getDefaultInstance().getNameEn2(); + return this; + } + + // optional sint32 interpolation = 5; + public boolean hasInterpolation() { + return result.hasInterpolation(); + } + public int getInterpolation() { + return result.getInterpolation(); + } + public Builder setInterpolation(int value) { + result.hasInterpolation = true; + result.interpolation_ = value; + return this; + } + public Builder clearInterpolation() { + result.hasInterpolation = false; + result.interpolation_ = 0; + return this; + } + + // required sint32 x = 7; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // required sint32 y = 8; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // optional sint32 x2 = 9; + public boolean hasX2() { + return result.hasX2(); + } + public int getX2() { + return result.getX2(); + } + public Builder setX2(int value) { + result.hasX2 = true; + result.x2_ = value; + return this; + } + public Builder clearX2() { + result.hasX2 = false; + result.x2_ = 0; + return this; + } + + // optional sint32 y2 = 10; + public boolean hasY2() { + return result.hasY2(); + } + public int getY2() { + return result.getY2(); + } + public Builder setY2(int value) { + result.hasY2 = true; + result.y2_ = value; + return this; + } + public Builder clearY2() { + result.hasY2 = false; + result.y2_ = 0; + return this; + } + + // optional uint64 id = 13; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // optional string postcode = 14; + public boolean hasPostcode() { + return result.hasPostcode(); + } + public java.lang.String getPostcode() { + return result.getPostcode(); + } + public Builder setPostcode(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPostcode = true; + result.postcode_ = value; + return this; + } + public Builder clearPostcode() { + result.hasPostcode = false; + result.postcode_ = getDefaultInstance().getPostcode(); + return this; + } + + // @@protoc_insertion_point(builder_scope:BuildingIndex) + } + + static { + defaultInstance = new BuildingIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:BuildingIndex) + } + + public static final class TransportRoutes extends + com.google.protobuf.GeneratedMessage { + // Use TransportRoutes.newBuilder() to construct. + private TransportRoutes() { + initFields(); + } + private TransportRoutes(boolean noInit) {} + + private static final TransportRoutes defaultInstance; + public static TransportRoutes getDefaultInstance() { + return defaultInstance; + } + + @Override + public TransportRoutes getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_TransportRoutes_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_TransportRoutes_fieldAccessorTable; + } + + // repeated .TransportRoute routes = 6; + public static final int ROUTES_FIELD_NUMBER = 6; + private java.util.List routes_ = + java.util.Collections.emptyList(); + public java.util.List getRoutesList() { + return routes_; + } + public int getRoutesCount() { return routes_.size(); } + public net.osmand.binary.OsmandOdb.TransportRoute getRoutes(int index) { + return routes_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + for (net.osmand.binary.OsmandOdb.TransportRoute element : getRoutesList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (net.osmand.binary.OsmandOdb.TransportRoute element : getRoutesList()) { + output.writeMessage(6, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + for (net.osmand.binary.OsmandOdb.TransportRoute element : getRoutesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoutes parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.TransportRoutes prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.TransportRoutes result; + + // Construct using net.osmand.binary.OsmandOdb.TransportRoutes.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.TransportRoutes(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.TransportRoutes internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.TransportRoutes(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.TransportRoutes.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportRoutes getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.TransportRoutes.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.TransportRoutes build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.TransportRoutes buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportRoutes buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.routes_ != java.util.Collections.EMPTY_LIST) { + result.routes_ = + java.util.Collections.unmodifiableList(result.routes_); + } + net.osmand.binary.OsmandOdb.TransportRoutes returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.TransportRoutes) { + return mergeFrom((net.osmand.binary.OsmandOdb.TransportRoutes)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.TransportRoutes other) { + if (other == net.osmand.binary.OsmandOdb.TransportRoutes.getDefaultInstance()) return this; + if (!other.routes_.isEmpty()) { + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + result.routes_.addAll(other.routes_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 50: { + net.osmand.binary.OsmandOdb.TransportRoute.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportRoute.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRoutes(subBuilder.buildPartial()); + break; + } + } + } + } + + + // repeated .TransportRoute routes = 6; + public java.util.List getRoutesList() { + return java.util.Collections.unmodifiableList(result.routes_); + } + public int getRoutesCount() { + return result.getRoutesCount(); + } + public net.osmand.binary.OsmandOdb.TransportRoute getRoutes(int index) { + return result.getRoutes(index); + } + public Builder setRoutes(int index, net.osmand.binary.OsmandOdb.TransportRoute value) { + if (value == null) { + throw new NullPointerException(); + } + result.routes_.set(index, value); + return this; + } + public Builder setRoutes(int index, net.osmand.binary.OsmandOdb.TransportRoute.Builder builderForValue) { + result.routes_.set(index, builderForValue.build()); + return this; + } + public Builder addRoutes(net.osmand.binary.OsmandOdb.TransportRoute value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + result.routes_.add(value); + return this; + } + public Builder addRoutes(net.osmand.binary.OsmandOdb.TransportRoute.Builder builderForValue) { + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + result.routes_.add(builderForValue.build()); + return this; + } + public Builder addAllRoutes( + java.lang.Iterable values) { + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + super.addAll(values, result.routes_); + return this; + } + public Builder clearRoutes() { + result.routes_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:TransportRoutes) + } + + static { + defaultInstance = new TransportRoutes(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TransportRoutes) + } + + public static final class TransportRoute extends + com.google.protobuf.GeneratedMessage { + // Use TransportRoute.newBuilder() to construct. + private TransportRoute() { + initFields(); + } + private TransportRoute(boolean noInit) {} + + private static final TransportRoute defaultInstance; + public static TransportRoute getDefaultInstance() { + return defaultInstance; + } + + @Override + public TransportRoute getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_TransportRoute_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_TransportRoute_fieldAccessorTable; + } + + // required uint64 id = 1; + public static final int ID_FIELD_NUMBER = 1; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // optional uint32 type = 3; + public static final int TYPE_FIELD_NUMBER = 3; + private boolean hasType; + private int type_ = 0; + public boolean hasType() { return hasType; } + public int getType() { return type_; } + + // optional uint32 operator = 4; + public static final int OPERATOR_FIELD_NUMBER = 4; + private boolean hasOperator; + private int operator_ = 0; + public boolean hasOperator() { return hasOperator; } + public int getOperator() { return operator_; } + + // optional string ref = 5; + public static final int REF_FIELD_NUMBER = 5; + private boolean hasRef; + private java.lang.String ref_ = ""; + public boolean hasRef() { return hasRef; } + public java.lang.String getRef() { return ref_; } + + // optional uint32 name = 6; + public static final int NAME_FIELD_NUMBER = 6; + private boolean hasName; + private int name_ = 0; + public boolean hasName() { return hasName; } + public int getName() { return name_; } + + // optional uint32 name_en = 7; + public static final int NAME_EN_FIELD_NUMBER = 7; + private boolean hasNameEn; + private int nameEn_ = 0; + public boolean hasNameEn() { return hasNameEn; } + public int getNameEn() { return nameEn_; } + + // optional uint32 distance = 8; + public static final int DISTANCE_FIELD_NUMBER = 8; + private boolean hasDistance; + private int distance_ = 0; + public boolean hasDistance() { return hasDistance; } + public int getDistance() { return distance_; } + + // repeated .TransportRouteStop directStops = 15; + public static final int DIRECTSTOPS_FIELD_NUMBER = 15; + private java.util.List directStops_ = + java.util.Collections.emptyList(); + public java.util.List getDirectStopsList() { + return directStops_; + } + public int getDirectStopsCount() { return directStops_.size(); } + public net.osmand.binary.OsmandOdb.TransportRouteStop getDirectStops(int index) { + return directStops_.get(index); + } + + // repeated .TransportRouteStop reverseStops = 16; + public static final int REVERSESTOPS_FIELD_NUMBER = 16; + private java.util.List reverseStops_ = + java.util.Collections.emptyList(); + public java.util.List getReverseStopsList() { + return reverseStops_; + } + public int getReverseStopsCount() { return reverseStops_.size(); } + public net.osmand.binary.OsmandOdb.TransportRouteStop getReverseStops(int index) { + return reverseStops_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasId) return false; + for (net.osmand.binary.OsmandOdb.TransportRouteStop element : getDirectStopsList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.TransportRouteStop element : getReverseStopsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasId()) { + output.writeUInt64(1, getId()); + } + if (hasType()) { + output.writeUInt32(3, getType()); + } + if (hasOperator()) { + output.writeUInt32(4, getOperator()); + } + if (hasRef()) { + output.writeString(5, getRef()); + } + if (hasName()) { + output.writeUInt32(6, getName()); + } + if (hasNameEn()) { + output.writeUInt32(7, getNameEn()); + } + if (hasDistance()) { + output.writeUInt32(8, getDistance()); + } + for (net.osmand.binary.OsmandOdb.TransportRouteStop element : getDirectStopsList()) { + output.writeMessage(15, element); + } + for (net.osmand.binary.OsmandOdb.TransportRouteStop element : getReverseStopsList()) { + output.writeMessage(16, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(1, getId()); + } + if (hasType()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(3, getType()); + } + if (hasOperator()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(4, getOperator()); + } + if (hasRef()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(5, getRef()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(6, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(7, getNameEn()); + } + if (hasDistance()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(8, getDistance()); + } + for (net.osmand.binary.OsmandOdb.TransportRouteStop element : getDirectStopsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(15, element); + } + for (net.osmand.binary.OsmandOdb.TransportRouteStop element : getReverseStopsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(16, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRoute parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.TransportRoute prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.TransportRoute result; + + // Construct using net.osmand.binary.OsmandOdb.TransportRoute.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.TransportRoute(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.TransportRoute internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.TransportRoute(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.TransportRoute.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportRoute getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.TransportRoute.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.TransportRoute build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.TransportRoute buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportRoute buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.directStops_ != java.util.Collections.EMPTY_LIST) { + result.directStops_ = + java.util.Collections.unmodifiableList(result.directStops_); + } + if (result.reverseStops_ != java.util.Collections.EMPTY_LIST) { + result.reverseStops_ = + java.util.Collections.unmodifiableList(result.reverseStops_); + } + net.osmand.binary.OsmandOdb.TransportRoute returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.TransportRoute) { + return mergeFrom((net.osmand.binary.OsmandOdb.TransportRoute)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.TransportRoute other) { + if (other == net.osmand.binary.OsmandOdb.TransportRoute.getDefaultInstance()) return this; + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasType()) { + setType(other.getType()); + } + if (other.hasOperator()) { + setOperator(other.getOperator()); + } + if (other.hasRef()) { + setRef(other.getRef()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasDistance()) { + setDistance(other.getDistance()); + } + if (!other.directStops_.isEmpty()) { + if (result.directStops_.isEmpty()) { + result.directStops_ = new java.util.ArrayList(); + } + result.directStops_.addAll(other.directStops_); + } + if (!other.reverseStops_.isEmpty()) { + if (result.reverseStops_.isEmpty()) { + result.reverseStops_ = new java.util.ArrayList(); + } + result.reverseStops_.addAll(other.reverseStops_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setId(input.readUInt64()); + break; + } + case 24: { + setType(input.readUInt32()); + break; + } + case 32: { + setOperator(input.readUInt32()); + break; + } + case 42: { + setRef(input.readString()); + break; + } + case 48: { + setName(input.readUInt32()); + break; + } + case 56: { + setNameEn(input.readUInt32()); + break; + } + case 64: { + setDistance(input.readUInt32()); + break; + } + case 122: { + net.osmand.binary.OsmandOdb.TransportRouteStop.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportRouteStop.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addDirectStops(subBuilder.buildPartial()); + break; + } + case 130: { + net.osmand.binary.OsmandOdb.TransportRouteStop.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportRouteStop.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addReverseStops(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required uint64 id = 1; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // optional uint32 type = 3; + public boolean hasType() { + return result.hasType(); + } + public int getType() { + return result.getType(); + } + public Builder setType(int value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder clearType() { + result.hasType = false; + result.type_ = 0; + return this; + } + + // optional uint32 operator = 4; + public boolean hasOperator() { + return result.hasOperator(); + } + public int getOperator() { + return result.getOperator(); + } + public Builder setOperator(int value) { + result.hasOperator = true; + result.operator_ = value; + return this; + } + public Builder clearOperator() { + result.hasOperator = false; + result.operator_ = 0; + return this; + } + + // optional string ref = 5; + public boolean hasRef() { + return result.hasRef(); + } + public java.lang.String getRef() { + return result.getRef(); + } + public Builder setRef(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasRef = true; + result.ref_ = value; + return this; + } + public Builder clearRef() { + result.hasRef = false; + result.ref_ = getDefaultInstance().getRef(); + return this; + } + + // optional uint32 name = 6; + public boolean hasName() { + return result.hasName(); + } + public int getName() { + return result.getName(); + } + public Builder setName(int value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = 0; + return this; + } + + // optional uint32 name_en = 7; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public int getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(int value) { + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = 0; + return this; + } + + // optional uint32 distance = 8; + public boolean hasDistance() { + return result.hasDistance(); + } + public int getDistance() { + return result.getDistance(); + } + public Builder setDistance(int value) { + result.hasDistance = true; + result.distance_ = value; + return this; + } + public Builder clearDistance() { + result.hasDistance = false; + result.distance_ = 0; + return this; + } + + // repeated .TransportRouteStop directStops = 15; + public java.util.List getDirectStopsList() { + return java.util.Collections.unmodifiableList(result.directStops_); + } + public int getDirectStopsCount() { + return result.getDirectStopsCount(); + } + public net.osmand.binary.OsmandOdb.TransportRouteStop getDirectStops(int index) { + return result.getDirectStops(index); + } + public Builder setDirectStops(int index, net.osmand.binary.OsmandOdb.TransportRouteStop value) { + if (value == null) { + throw new NullPointerException(); + } + result.directStops_.set(index, value); + return this; + } + public Builder setDirectStops(int index, net.osmand.binary.OsmandOdb.TransportRouteStop.Builder builderForValue) { + result.directStops_.set(index, builderForValue.build()); + return this; + } + public Builder addDirectStops(net.osmand.binary.OsmandOdb.TransportRouteStop value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.directStops_.isEmpty()) { + result.directStops_ = new java.util.ArrayList(); + } + result.directStops_.add(value); + return this; + } + public Builder addDirectStops(net.osmand.binary.OsmandOdb.TransportRouteStop.Builder builderForValue) { + if (result.directStops_.isEmpty()) { + result.directStops_ = new java.util.ArrayList(); + } + result.directStops_.add(builderForValue.build()); + return this; + } + public Builder addAllDirectStops( + java.lang.Iterable values) { + if (result.directStops_.isEmpty()) { + result.directStops_ = new java.util.ArrayList(); + } + super.addAll(values, result.directStops_); + return this; + } + public Builder clearDirectStops() { + result.directStops_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .TransportRouteStop reverseStops = 16; + public java.util.List getReverseStopsList() { + return java.util.Collections.unmodifiableList(result.reverseStops_); + } + public int getReverseStopsCount() { + return result.getReverseStopsCount(); + } + public net.osmand.binary.OsmandOdb.TransportRouteStop getReverseStops(int index) { + return result.getReverseStops(index); + } + public Builder setReverseStops(int index, net.osmand.binary.OsmandOdb.TransportRouteStop value) { + if (value == null) { + throw new NullPointerException(); + } + result.reverseStops_.set(index, value); + return this; + } + public Builder setReverseStops(int index, net.osmand.binary.OsmandOdb.TransportRouteStop.Builder builderForValue) { + result.reverseStops_.set(index, builderForValue.build()); + return this; + } + public Builder addReverseStops(net.osmand.binary.OsmandOdb.TransportRouteStop value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.reverseStops_.isEmpty()) { + result.reverseStops_ = new java.util.ArrayList(); + } + result.reverseStops_.add(value); + return this; + } + public Builder addReverseStops(net.osmand.binary.OsmandOdb.TransportRouteStop.Builder builderForValue) { + if (result.reverseStops_.isEmpty()) { + result.reverseStops_ = new java.util.ArrayList(); + } + result.reverseStops_.add(builderForValue.build()); + return this; + } + public Builder addAllReverseStops( + java.lang.Iterable values) { + if (result.reverseStops_.isEmpty()) { + result.reverseStops_ = new java.util.ArrayList(); + } + super.addAll(values, result.reverseStops_); + return this; + } + public Builder clearReverseStops() { + result.reverseStops_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:TransportRoute) + } + + static { + defaultInstance = new TransportRoute(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TransportRoute) + } + + public static final class TransportRouteStop extends + com.google.protobuf.GeneratedMessage { + // Use TransportRouteStop.newBuilder() to construct. + private TransportRouteStop() { + initFields(); + } + private TransportRouteStop(boolean noInit) {} + + private static final TransportRouteStop defaultInstance; + public static TransportRouteStop getDefaultInstance() { + return defaultInstance; + } + + @Override + public TransportRouteStop getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_TransportRouteStop_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_TransportRouteStop_fieldAccessorTable; + } + + // required sint64 id = 1; + public static final int ID_FIELD_NUMBER = 1; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // required sint32 dx = 2; + public static final int DX_FIELD_NUMBER = 2; + private boolean hasDx; + private int dx_ = 0; + public boolean hasDx() { return hasDx; } + public int getDx() { return dx_; } + + // required sint32 dy = 3; + public static final int DY_FIELD_NUMBER = 3; + private boolean hasDy; + private int dy_ = 0; + public boolean hasDy() { return hasDy; } + public int getDy() { return dy_; } + + // required uint32 name = 6; + public static final int NAME_FIELD_NUMBER = 6; + private boolean hasName; + private int name_ = 0; + public boolean hasName() { return hasName; } + public int getName() { return name_; } + + // optional uint32 name_en = 7; + public static final int NAME_EN_FIELD_NUMBER = 7; + private boolean hasNameEn; + private int nameEn_ = 0; + public boolean hasNameEn() { return hasNameEn; } + public int getNameEn() { return nameEn_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasId) return false; + if (!hasDx) return false; + if (!hasDy) return false; + if (!hasName) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasId()) { + output.writeSInt64(1, getId()); + } + if (hasDx()) { + output.writeSInt32(2, getDx()); + } + if (hasDy()) { + output.writeSInt32(3, getDy()); + } + if (hasName()) { + output.writeUInt32(6, getName()); + } + if (hasNameEn()) { + output.writeUInt32(7, getNameEn()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt64Size(1, getId()); + } + if (hasDx()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getDx()); + } + if (hasDy()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getDy()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(6, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(7, getNameEn()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportRouteStop parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.TransportRouteStop prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.TransportRouteStop result; + + // Construct using net.osmand.binary.OsmandOdb.TransportRouteStop.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.TransportRouteStop(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.TransportRouteStop internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.TransportRouteStop(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.TransportRouteStop.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportRouteStop getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.TransportRouteStop.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.TransportRouteStop build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.TransportRouteStop buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportRouteStop buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.TransportRouteStop returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.TransportRouteStop) { + return mergeFrom((net.osmand.binary.OsmandOdb.TransportRouteStop)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.TransportRouteStop other) { + if (other == net.osmand.binary.OsmandOdb.TransportRouteStop.getDefaultInstance()) return this; + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasDx()) { + setDx(other.getDx()); + } + if (other.hasDy()) { + setDy(other.getDy()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setId(input.readSInt64()); + break; + } + case 16: { + setDx(input.readSInt32()); + break; + } + case 24: { + setDy(input.readSInt32()); + break; + } + case 48: { + setName(input.readUInt32()); + break; + } + case 56: { + setNameEn(input.readUInt32()); + break; + } + } + } + } + + + // required sint64 id = 1; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // required sint32 dx = 2; + public boolean hasDx() { + return result.hasDx(); + } + public int getDx() { + return result.getDx(); + } + public Builder setDx(int value) { + result.hasDx = true; + result.dx_ = value; + return this; + } + public Builder clearDx() { + result.hasDx = false; + result.dx_ = 0; + return this; + } + + // required sint32 dy = 3; + public boolean hasDy() { + return result.hasDy(); + } + public int getDy() { + return result.getDy(); + } + public Builder setDy(int value) { + result.hasDy = true; + result.dy_ = value; + return this; + } + public Builder clearDy() { + result.hasDy = false; + result.dy_ = 0; + return this; + } + + // required uint32 name = 6; + public boolean hasName() { + return result.hasName(); + } + public int getName() { + return result.getName(); + } + public Builder setName(int value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = 0; + return this; + } + + // optional uint32 name_en = 7; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public int getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(int value) { + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:TransportRouteStop) + } + + static { + defaultInstance = new TransportRouteStop(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TransportRouteStop) + } + + public static final class TransportStop extends + com.google.protobuf.GeneratedMessage { + // Use TransportStop.newBuilder() to construct. + private TransportStop() { + initFields(); + } + private TransportStop(boolean noInit) {} + + private static final TransportStop defaultInstance; + public static TransportStop getDefaultInstance() { + return defaultInstance; + } + + @Override + public TransportStop getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_TransportStop_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_TransportStop_fieldAccessorTable; + } + + // required sint32 dx = 1; + public static final int DX_FIELD_NUMBER = 1; + private boolean hasDx; + private int dx_ = 0; + public boolean hasDx() { return hasDx; } + public int getDx() { return dx_; } + + // required sint32 dy = 2; + public static final int DY_FIELD_NUMBER = 2; + private boolean hasDy; + private int dy_ = 0; + public boolean hasDy() { return hasDy; } + public int getDy() { return dy_; } + + // required sint64 id = 5; + public static final int ID_FIELD_NUMBER = 5; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // required uint32 name = 6; + public static final int NAME_FIELD_NUMBER = 6; + private boolean hasName; + private int name_ = 0; + public boolean hasName() { return hasName; } + public int getName() { return name_; } + + // optional uint32 name_en = 7; + public static final int NAME_EN_FIELD_NUMBER = 7; + private boolean hasNameEn; + private int nameEn_ = 0; + public boolean hasNameEn() { return hasNameEn; } + public int getNameEn() { return nameEn_; } + + // repeated uint32 routes = 16; + public static final int ROUTES_FIELD_NUMBER = 16; + private java.util.List routes_ = + java.util.Collections.emptyList(); + public java.util.List getRoutesList() { + return routes_; + } + public int getRoutesCount() { return routes_.size(); } + public int getRoutes(int index) { + return routes_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasDx) return false; + if (!hasDy) return false; + if (!hasId) return false; + if (!hasName) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasDx()) { + output.writeSInt32(1, getDx()); + } + if (hasDy()) { + output.writeSInt32(2, getDy()); + } + if (hasId()) { + output.writeSInt64(5, getId()); + } + if (hasName()) { + output.writeUInt32(6, getName()); + } + if (hasNameEn()) { + output.writeUInt32(7, getNameEn()); + } + for (int element : getRoutesList()) { + output.writeUInt32(16, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasDx()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(1, getDx()); + } + if (hasDy()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getDy()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt64Size(5, getId()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(6, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(7, getNameEn()); + } + { + int dataSize = 0; + for (int element : getRoutesList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeUInt32SizeNoTag(element); + } + size += dataSize; + size += 2 * getRoutesList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportStop parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStop parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.TransportStop prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.TransportStop result; + + // Construct using net.osmand.binary.OsmandOdb.TransportStop.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.TransportStop(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.TransportStop internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.TransportStop(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.TransportStop.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportStop getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.TransportStop.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.TransportStop build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.TransportStop buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportStop buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.routes_ != java.util.Collections.EMPTY_LIST) { + result.routes_ = + java.util.Collections.unmodifiableList(result.routes_); + } + net.osmand.binary.OsmandOdb.TransportStop returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.TransportStop) { + return mergeFrom((net.osmand.binary.OsmandOdb.TransportStop)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.TransportStop other) { + if (other == net.osmand.binary.OsmandOdb.TransportStop.getDefaultInstance()) return this; + if (other.hasDx()) { + setDx(other.getDx()); + } + if (other.hasDy()) { + setDy(other.getDy()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (!other.routes_.isEmpty()) { + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + result.routes_.addAll(other.routes_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setDx(input.readSInt32()); + break; + } + case 16: { + setDy(input.readSInt32()); + break; + } + case 40: { + setId(input.readSInt64()); + break; + } + case 48: { + setName(input.readUInt32()); + break; + } + case 56: { + setNameEn(input.readUInt32()); + break; + } + case 128: { + addRoutes(input.readUInt32()); + break; + } + case 130: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addRoutes(input.readUInt32()); + } + input.popLimit(limit); + break; + } + } + } + } + + + // required sint32 dx = 1; + public boolean hasDx() { + return result.hasDx(); + } + public int getDx() { + return result.getDx(); + } + public Builder setDx(int value) { + result.hasDx = true; + result.dx_ = value; + return this; + } + public Builder clearDx() { + result.hasDx = false; + result.dx_ = 0; + return this; + } + + // required sint32 dy = 2; + public boolean hasDy() { + return result.hasDy(); + } + public int getDy() { + return result.getDy(); + } + public Builder setDy(int value) { + result.hasDy = true; + result.dy_ = value; + return this; + } + public Builder clearDy() { + result.hasDy = false; + result.dy_ = 0; + return this; + } + + // required sint64 id = 5; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // required uint32 name = 6; + public boolean hasName() { + return result.hasName(); + } + public int getName() { + return result.getName(); + } + public Builder setName(int value) { + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = 0; + return this; + } + + // optional uint32 name_en = 7; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public int getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(int value) { + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = 0; + return this; + } + + // repeated uint32 routes = 16; + public java.util.List getRoutesList() { + return java.util.Collections.unmodifiableList(result.routes_); + } + public int getRoutesCount() { + return result.getRoutesCount(); + } + public int getRoutes(int index) { + return result.getRoutes(index); + } + public Builder setRoutes(int index, int value) { + result.routes_.set(index, value); + return this; + } + public Builder addRoutes(int value) { + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + result.routes_.add(value); + return this; + } + public Builder addAllRoutes( + java.lang.Iterable values) { + if (result.routes_.isEmpty()) { + result.routes_ = new java.util.ArrayList(); + } + super.addAll(values, result.routes_); + return this; + } + public Builder clearRoutes() { + result.routes_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:TransportStop) + } + + static { + defaultInstance = new TransportStop(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TransportStop) + } + + public static final class TransportStopsTree extends + com.google.protobuf.GeneratedMessage { + // Use TransportStopsTree.newBuilder() to construct. + private TransportStopsTree() { + initFields(); + } + private TransportStopsTree(boolean noInit) {} + + private static final TransportStopsTree defaultInstance; + public static TransportStopsTree getDefaultInstance() { + return defaultInstance; + } + + @Override + public TransportStopsTree getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_TransportStopsTree_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_TransportStopsTree_fieldAccessorTable; + } + + // required sint32 left = 1; + public static final int LEFT_FIELD_NUMBER = 1; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required sint32 right = 2; + public static final int RIGHT_FIELD_NUMBER = 2; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required sint32 top = 3; + public static final int TOP_FIELD_NUMBER = 3; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required sint32 bottom = 4; + public static final int BOTTOM_FIELD_NUMBER = 4; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // repeated .TransportStopsTree subtrees = 7; + public static final int SUBTREES_FIELD_NUMBER = 7; + private java.util.List subtrees_ = + java.util.Collections.emptyList(); + public java.util.List getSubtreesList() { + return subtrees_; + } + public int getSubtreesCount() { return subtrees_.size(); } + public net.osmand.binary.OsmandOdb.TransportStopsTree getSubtrees(int index) { + return subtrees_.get(index); + } + + // repeated .TransportStop leafs = 8; + public static final int LEAFS_FIELD_NUMBER = 8; + private java.util.List leafs_ = + java.util.Collections.emptyList(); + public java.util.List getLeafsList() { + return leafs_; + } + public int getLeafsCount() { return leafs_.size(); } + public net.osmand.binary.OsmandOdb.TransportStop getLeafs(int index) { + return leafs_.get(index); + } + + // optional uint64 baseId = 16; + public static final int BASEID_FIELD_NUMBER = 16; + private boolean hasBaseId; + private long baseId_ = 0L; + public boolean hasBaseId() { return hasBaseId; } + public long getBaseId() { return baseId_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + for (net.osmand.binary.OsmandOdb.TransportStopsTree element : getSubtreesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.TransportStop element : getLeafsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasLeft()) { + output.writeSInt32(1, getLeft()); + } + if (hasRight()) { + output.writeSInt32(2, getRight()); + } + if (hasTop()) { + output.writeSInt32(3, getTop()); + } + if (hasBottom()) { + output.writeSInt32(4, getBottom()); + } + for (net.osmand.binary.OsmandOdb.TransportStopsTree element : getSubtreesList()) { + output.writeMessage(7, element); + } + for (net.osmand.binary.OsmandOdb.TransportStop element : getLeafsList()) { + output.writeMessage(8, element); + } + if (hasBaseId()) { + output.writeUInt64(16, getBaseId()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(1, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(4, getBottom()); + } + for (net.osmand.binary.OsmandOdb.TransportStopsTree element : getSubtreesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + for (net.osmand.binary.OsmandOdb.TransportStop element : getLeafsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, element); + } + if (hasBaseId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(16, getBaseId()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.TransportStopsTree parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.TransportStopsTree prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.TransportStopsTree result; + + // Construct using net.osmand.binary.OsmandOdb.TransportStopsTree.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.TransportStopsTree(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.TransportStopsTree internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.TransportStopsTree(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.TransportStopsTree.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportStopsTree getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.TransportStopsTree.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.TransportStopsTree build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.TransportStopsTree buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.TransportStopsTree buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.subtrees_ != java.util.Collections.EMPTY_LIST) { + result.subtrees_ = + java.util.Collections.unmodifiableList(result.subtrees_); + } + if (result.leafs_ != java.util.Collections.EMPTY_LIST) { + result.leafs_ = + java.util.Collections.unmodifiableList(result.leafs_); + } + net.osmand.binary.OsmandOdb.TransportStopsTree returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.TransportStopsTree) { + return mergeFrom((net.osmand.binary.OsmandOdb.TransportStopsTree)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.TransportStopsTree other) { + if (other == net.osmand.binary.OsmandOdb.TransportStopsTree.getDefaultInstance()) return this; + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (!other.subtrees_.isEmpty()) { + if (result.subtrees_.isEmpty()) { + result.subtrees_ = new java.util.ArrayList(); + } + result.subtrees_.addAll(other.subtrees_); + } + if (!other.leafs_.isEmpty()) { + if (result.leafs_.isEmpty()) { + result.leafs_ = new java.util.ArrayList(); + } + result.leafs_.addAll(other.leafs_); + } + if (other.hasBaseId()) { + setBaseId(other.getBaseId()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setLeft(input.readSInt32()); + break; + } + case 16: { + setRight(input.readSInt32()); + break; + } + case 24: { + setTop(input.readSInt32()); + break; + } + case 32: { + setBottom(input.readSInt32()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.TransportStopsTree.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportStopsTree.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addSubtrees(subBuilder.buildPartial()); + break; + } + case 66: { + net.osmand.binary.OsmandOdb.TransportStop.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportStop.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addLeafs(subBuilder.buildPartial()); + break; + } + case 128: { + setBaseId(input.readUInt64()); + break; + } + } + } + } + + + // required sint32 left = 1; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required sint32 right = 2; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required sint32 top = 3; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required sint32 bottom = 4; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // repeated .TransportStopsTree subtrees = 7; + public java.util.List getSubtreesList() { + return java.util.Collections.unmodifiableList(result.subtrees_); + } + public int getSubtreesCount() { + return result.getSubtreesCount(); + } + public net.osmand.binary.OsmandOdb.TransportStopsTree getSubtrees(int index) { + return result.getSubtrees(index); + } + public Builder setSubtrees(int index, net.osmand.binary.OsmandOdb.TransportStopsTree value) { + if (value == null) { + throw new NullPointerException(); + } + result.subtrees_.set(index, value); + return this; + } + public Builder setSubtrees(int index, net.osmand.binary.OsmandOdb.TransportStopsTree.Builder builderForValue) { + result.subtrees_.set(index, builderForValue.build()); + return this; + } + public Builder addSubtrees(net.osmand.binary.OsmandOdb.TransportStopsTree value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.subtrees_.isEmpty()) { + result.subtrees_ = new java.util.ArrayList(); + } + result.subtrees_.add(value); + return this; + } + public Builder addSubtrees(net.osmand.binary.OsmandOdb.TransportStopsTree.Builder builderForValue) { + if (result.subtrees_.isEmpty()) { + result.subtrees_ = new java.util.ArrayList(); + } + result.subtrees_.add(builderForValue.build()); + return this; + } + public Builder addAllSubtrees( + java.lang.Iterable values) { + if (result.subtrees_.isEmpty()) { + result.subtrees_ = new java.util.ArrayList(); + } + super.addAll(values, result.subtrees_); + return this; + } + public Builder clearSubtrees() { + result.subtrees_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .TransportStop leafs = 8; + public java.util.List getLeafsList() { + return java.util.Collections.unmodifiableList(result.leafs_); + } + public int getLeafsCount() { + return result.getLeafsCount(); + } + public net.osmand.binary.OsmandOdb.TransportStop getLeafs(int index) { + return result.getLeafs(index); + } + public Builder setLeafs(int index, net.osmand.binary.OsmandOdb.TransportStop value) { + if (value == null) { + throw new NullPointerException(); + } + result.leafs_.set(index, value); + return this; + } + public Builder setLeafs(int index, net.osmand.binary.OsmandOdb.TransportStop.Builder builderForValue) { + result.leafs_.set(index, builderForValue.build()); + return this; + } + public Builder addLeafs(net.osmand.binary.OsmandOdb.TransportStop value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.leafs_.isEmpty()) { + result.leafs_ = new java.util.ArrayList(); + } + result.leafs_.add(value); + return this; + } + public Builder addLeafs(net.osmand.binary.OsmandOdb.TransportStop.Builder builderForValue) { + if (result.leafs_.isEmpty()) { + result.leafs_ = new java.util.ArrayList(); + } + result.leafs_.add(builderForValue.build()); + return this; + } + public Builder addAllLeafs( + java.lang.Iterable values) { + if (result.leafs_.isEmpty()) { + result.leafs_ = new java.util.ArrayList(); + } + super.addAll(values, result.leafs_); + return this; + } + public Builder clearLeafs() { + result.leafs_ = java.util.Collections.emptyList(); + return this; + } + + // optional uint64 baseId = 16; + public boolean hasBaseId() { + return result.hasBaseId(); + } + public long getBaseId() { + return result.getBaseId(); + } + public Builder setBaseId(long value) { + result.hasBaseId = true; + result.baseId_ = value; + return this; + } + public Builder clearBaseId() { + result.hasBaseId = false; + result.baseId_ = 0L; + return this; + } + + // @@protoc_insertion_point(builder_scope:TransportStopsTree) + } + + static { + defaultInstance = new TransportStopsTree(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TransportStopsTree) + } + + public static final class OsmAndTransportIndex extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndTransportIndex.newBuilder() to construct. + private OsmAndTransportIndex() { + initFields(); + } + private OsmAndTransportIndex(boolean noInit) {} + + private static final OsmAndTransportIndex defaultInstance; + public static OsmAndTransportIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndTransportIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndTransportIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndTransportIndex_fieldAccessorTable; + } + + // optional string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional .TransportRoutes routes = 3; + public static final int ROUTES_FIELD_NUMBER = 3; + private boolean hasRoutes; + private net.osmand.binary.OsmandOdb.TransportRoutes routes_; + public boolean hasRoutes() { return hasRoutes; } + public net.osmand.binary.OsmandOdb.TransportRoutes getRoutes() { return routes_; } + + // optional .TransportStopsTree stops = 6; + public static final int STOPS_FIELD_NUMBER = 6; + private boolean hasStops; + private net.osmand.binary.OsmandOdb.TransportStopsTree stops_; + public boolean hasStops() { return hasStops; } + public net.osmand.binary.OsmandOdb.TransportStopsTree getStops() { return stops_; } + + // required .StringTable stringTable = 9; + public static final int STRINGTABLE_FIELD_NUMBER = 9; + private boolean hasStringTable; + private net.osmand.binary.OsmandOdb.StringTable stringTable_; + public boolean hasStringTable() { return hasStringTable; } + public net.osmand.binary.OsmandOdb.StringTable getStringTable() { return stringTable_; } + + private void initFields() { + routes_ = net.osmand.binary.OsmandOdb.TransportRoutes.getDefaultInstance(); + stops_ = net.osmand.binary.OsmandOdb.TransportStopsTree.getDefaultInstance(); + stringTable_ = net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasStringTable) return false; + if (hasRoutes()) { + if (!getRoutes().isInitialized()) return false; + } + if (hasStops()) { + if (!getStops().isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasRoutes()) { + output.writeMessage(3, getRoutes()); + } + if (hasStops()) { + output.writeMessage(6, getStops()); + } + if (hasStringTable()) { + output.writeMessage(9, getStringTable()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasRoutes()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getRoutes()); + } + if (hasStops()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getStops()); + } + if (hasStringTable()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, getStringTable()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndTransportIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndTransportIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndTransportIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndTransportIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndTransportIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndTransportIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndTransportIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndTransportIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndTransportIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndTransportIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndTransportIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndTransportIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndTransportIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndTransportIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndTransportIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndTransportIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndTransportIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndTransportIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasRoutes()) { + mergeRoutes(other.getRoutes()); + } + if (other.hasStops()) { + mergeStops(other.getStops()); + } + if (other.hasStringTable()) { + mergeStringTable(other.getStringTable()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 26: { + net.osmand.binary.OsmandOdb.TransportRoutes.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportRoutes.newBuilder(); + if (hasRoutes()) { + subBuilder.mergeFrom(getRoutes()); + } + input.readMessage(subBuilder, extensionRegistry); + setRoutes(subBuilder.buildPartial()); + break; + } + case 50: { + net.osmand.binary.OsmandOdb.TransportStopsTree.Builder subBuilder = net.osmand.binary.OsmandOdb.TransportStopsTree.newBuilder(); + if (hasStops()) { + subBuilder.mergeFrom(getStops()); + } + input.readMessage(subBuilder, extensionRegistry); + setStops(subBuilder.buildPartial()); + break; + } + case 74: { + net.osmand.binary.OsmandOdb.StringTable.Builder subBuilder = net.osmand.binary.OsmandOdb.StringTable.newBuilder(); + if (hasStringTable()) { + subBuilder.mergeFrom(getStringTable()); + } + input.readMessage(subBuilder, extensionRegistry); + setStringTable(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional .TransportRoutes routes = 3; + public boolean hasRoutes() { + return result.hasRoutes(); + } + public net.osmand.binary.OsmandOdb.TransportRoutes getRoutes() { + return result.getRoutes(); + } + public Builder setRoutes(net.osmand.binary.OsmandOdb.TransportRoutes value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasRoutes = true; + result.routes_ = value; + return this; + } + public Builder setRoutes(net.osmand.binary.OsmandOdb.TransportRoutes.Builder builderForValue) { + result.hasRoutes = true; + result.routes_ = builderForValue.build(); + return this; + } + public Builder mergeRoutes(net.osmand.binary.OsmandOdb.TransportRoutes value) { + if (result.hasRoutes() && + result.routes_ != net.osmand.binary.OsmandOdb.TransportRoutes.getDefaultInstance()) { + result.routes_ = + net.osmand.binary.OsmandOdb.TransportRoutes.newBuilder(result.routes_).mergeFrom(value).buildPartial(); + } else { + result.routes_ = value; + } + result.hasRoutes = true; + return this; + } + public Builder clearRoutes() { + result.hasRoutes = false; + result.routes_ = net.osmand.binary.OsmandOdb.TransportRoutes.getDefaultInstance(); + return this; + } + + // optional .TransportStopsTree stops = 6; + public boolean hasStops() { + return result.hasStops(); + } + public net.osmand.binary.OsmandOdb.TransportStopsTree getStops() { + return result.getStops(); + } + public Builder setStops(net.osmand.binary.OsmandOdb.TransportStopsTree value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasStops = true; + result.stops_ = value; + return this; + } + public Builder setStops(net.osmand.binary.OsmandOdb.TransportStopsTree.Builder builderForValue) { + result.hasStops = true; + result.stops_ = builderForValue.build(); + return this; + } + public Builder mergeStops(net.osmand.binary.OsmandOdb.TransportStopsTree value) { + if (result.hasStops() && + result.stops_ != net.osmand.binary.OsmandOdb.TransportStopsTree.getDefaultInstance()) { + result.stops_ = + net.osmand.binary.OsmandOdb.TransportStopsTree.newBuilder(result.stops_).mergeFrom(value).buildPartial(); + } else { + result.stops_ = value; + } + result.hasStops = true; + return this; + } + public Builder clearStops() { + result.hasStops = false; + result.stops_ = net.osmand.binary.OsmandOdb.TransportStopsTree.getDefaultInstance(); + return this; + } + + // required .StringTable stringTable = 9; + public boolean hasStringTable() { + return result.hasStringTable(); + } + public net.osmand.binary.OsmandOdb.StringTable getStringTable() { + return result.getStringTable(); + } + public Builder setStringTable(net.osmand.binary.OsmandOdb.StringTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasStringTable = true; + result.stringTable_ = value; + return this; + } + public Builder setStringTable(net.osmand.binary.OsmandOdb.StringTable.Builder builderForValue) { + result.hasStringTable = true; + result.stringTable_ = builderForValue.build(); + return this; + } + public Builder mergeStringTable(net.osmand.binary.OsmandOdb.StringTable value) { + if (result.hasStringTable() && + result.stringTable_ != net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance()) { + result.stringTable_ = + net.osmand.binary.OsmandOdb.StringTable.newBuilder(result.stringTable_).mergeFrom(value).buildPartial(); + } else { + result.stringTable_ = value; + } + result.hasStringTable = true; + return this; + } + public Builder clearStringTable() { + result.hasStringTable = false; + result.stringTable_ = net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndTransportIndex) + } + + static { + defaultInstance = new OsmAndTransportIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndTransportIndex) + } + + public static final class OsmAndPoiIndex extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiIndex.newBuilder() to construct. + private OsmAndPoiIndex() { + initFields(); + } + private OsmAndPoiIndex(boolean noInit) {} + + private static final OsmAndPoiIndex defaultInstance; + public static OsmAndPoiIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiIndex_fieldAccessorTable; + } + + // required string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // required .OsmAndTileBox boundaries = 2; + public static final int BOUNDARIES_FIELD_NUMBER = 2; + private boolean hasBoundaries; + private net.osmand.binary.OsmandOdb.OsmAndTileBox boundaries_; + public boolean hasBoundaries() { return hasBoundaries; } + public net.osmand.binary.OsmandOdb.OsmAndTileBox getBoundaries() { return boundaries_; } + + // repeated .OsmAndCategoryTable categoriesTable = 3; + public static final int CATEGORIESTABLE_FIELD_NUMBER = 3; + private java.util.List categoriesTable_ = + java.util.Collections.emptyList(); + public java.util.List getCategoriesTableList() { + return categoriesTable_; + } + public int getCategoriesTableCount() { return categoriesTable_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndCategoryTable getCategoriesTable(int index) { + return categoriesTable_.get(index); + } + + // optional .OsmAndPoiNameIndex nameIndex = 4; + public static final int NAMEINDEX_FIELD_NUMBER = 4; + private boolean hasNameIndex; + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex nameIndex_; + public boolean hasNameIndex() { return hasNameIndex; } + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex getNameIndex() { return nameIndex_; } + + // repeated .OsmAndPoiBox boxes = 6; + public static final int BOXES_FIELD_NUMBER = 6; + private java.util.List boxes_ = + java.util.Collections.emptyList(); + public java.util.List getBoxesList() { + return boxes_; + } + public int getBoxesCount() { return boxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiBox getBoxes(int index) { + return boxes_.get(index); + } + + // repeated .OsmAndPoiBoxData poiData = 9; + public static final int POIDATA_FIELD_NUMBER = 9; + private java.util.List poiData_ = + java.util.Collections.emptyList(); + public java.util.List getPoiDataList() { + return poiData_; + } + public int getPoiDataCount() { return poiData_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxData getPoiData(int index) { + return poiData_.get(index); + } + + private void initFields() { + boundaries_ = net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + nameIndex_ = net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + if (!hasBoundaries) return false; + if (!getBoundaries().isInitialized()) return false; + for (net.osmand.binary.OsmandOdb.OsmAndCategoryTable element : getCategoriesTableList()) { + if (!element.isInitialized()) return false; + } + if (hasNameIndex()) { + if (!getNameIndex().isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBox element : getBoxesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBoxData element : getPoiDataList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + if (hasBoundaries()) { + output.writeMessage(2, getBoundaries()); + } + for (net.osmand.binary.OsmandOdb.OsmAndCategoryTable element : getCategoriesTableList()) { + output.writeMessage(3, element); + } + if (hasNameIndex()) { + output.writeMessage(4, getNameIndex()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBox element : getBoxesList()) { + output.writeMessage(6, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBoxData element : getPoiDataList()) { + output.writeMessage(9, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + if (hasBoundaries()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getBoundaries()); + } + for (net.osmand.binary.OsmandOdb.OsmAndCategoryTable element : getCategoriesTableList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, element); + } + if (hasNameIndex()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getNameIndex()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBox element : getBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBoxData element : getPoiDataList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.categoriesTable_ != java.util.Collections.EMPTY_LIST) { + result.categoriesTable_ = + java.util.Collections.unmodifiableList(result.categoriesTable_); + } + if (result.boxes_ != java.util.Collections.EMPTY_LIST) { + result.boxes_ = + java.util.Collections.unmodifiableList(result.boxes_); + } + if (result.poiData_ != java.util.Collections.EMPTY_LIST) { + result.poiData_ = + java.util.Collections.unmodifiableList(result.poiData_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasBoundaries()) { + mergeBoundaries(other.getBoundaries()); + } + if (!other.categoriesTable_.isEmpty()) { + if (result.categoriesTable_.isEmpty()) { + result.categoriesTable_ = new java.util.ArrayList(); + } + result.categoriesTable_.addAll(other.categoriesTable_); + } + if (other.hasNameIndex()) { + mergeNameIndex(other.getNameIndex()); + } + if (!other.boxes_.isEmpty()) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.addAll(other.boxes_); + } + if (!other.poiData_.isEmpty()) { + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + result.poiData_.addAll(other.poiData_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder(); + if (hasBoundaries()) { + subBuilder.mergeFrom(getBoundaries()); + } + input.readMessage(subBuilder, extensionRegistry); + setBoundaries(subBuilder.buildPartial()); + break; + } + case 26: { + net.osmand.binary.OsmandOdb.OsmAndCategoryTable.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndCategoryTable.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addCategoriesTable(subBuilder.buildPartial()); + break; + } + case 34: { + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.newBuilder(); + if (hasNameIndex()) { + subBuilder.mergeFrom(getNameIndex()); + } + input.readMessage(subBuilder, extensionRegistry); + setNameIndex(subBuilder.buildPartial()); + break; + } + case 50: { + net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBoxes(subBuilder.buildPartial()); + break; + } + case 74: { + net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPoiData(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // required .OsmAndTileBox boundaries = 2; + public boolean hasBoundaries() { + return result.hasBoundaries(); + } + public net.osmand.binary.OsmandOdb.OsmAndTileBox getBoundaries() { + return result.getBoundaries(); + } + public Builder setBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasBoundaries = true; + result.boundaries_ = value; + return this; + } + public Builder setBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder builderForValue) { + result.hasBoundaries = true; + result.boundaries_ = builderForValue.build(); + return this; + } + public Builder mergeBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox value) { + if (result.hasBoundaries() && + result.boundaries_ != net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance()) { + result.boundaries_ = + net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder(result.boundaries_).mergeFrom(value).buildPartial(); + } else { + result.boundaries_ = value; + } + result.hasBoundaries = true; + return this; + } + public Builder clearBoundaries() { + result.hasBoundaries = false; + result.boundaries_ = net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + return this; + } + + // repeated .OsmAndCategoryTable categoriesTable = 3; + public java.util.List getCategoriesTableList() { + return java.util.Collections.unmodifiableList(result.categoriesTable_); + } + public int getCategoriesTableCount() { + return result.getCategoriesTableCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndCategoryTable getCategoriesTable(int index) { + return result.getCategoriesTable(index); + } + public Builder setCategoriesTable(int index, net.osmand.binary.OsmandOdb.OsmAndCategoryTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.categoriesTable_.set(index, value); + return this; + } + public Builder setCategoriesTable(int index, net.osmand.binary.OsmandOdb.OsmAndCategoryTable.Builder builderForValue) { + result.categoriesTable_.set(index, builderForValue.build()); + return this; + } + public Builder addCategoriesTable(net.osmand.binary.OsmandOdb.OsmAndCategoryTable value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.categoriesTable_.isEmpty()) { + result.categoriesTable_ = new java.util.ArrayList(); + } + result.categoriesTable_.add(value); + return this; + } + public Builder addCategoriesTable(net.osmand.binary.OsmandOdb.OsmAndCategoryTable.Builder builderForValue) { + if (result.categoriesTable_.isEmpty()) { + result.categoriesTable_ = new java.util.ArrayList(); + } + result.categoriesTable_.add(builderForValue.build()); + return this; + } + public Builder addAllCategoriesTable( + java.lang.Iterable values) { + if (result.categoriesTable_.isEmpty()) { + result.categoriesTable_ = new java.util.ArrayList(); + } + super.addAll(values, result.categoriesTable_); + return this; + } + public Builder clearCategoriesTable() { + result.categoriesTable_ = java.util.Collections.emptyList(); + return this; + } + + // optional .OsmAndPoiNameIndex nameIndex = 4; + public boolean hasNameIndex() { + return result.hasNameIndex(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex getNameIndex() { + return result.getNameIndex(); + } + public Builder setNameIndex(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameIndex = true; + result.nameIndex_ = value; + return this; + } + public Builder setNameIndex(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.Builder builderForValue) { + result.hasNameIndex = true; + result.nameIndex_ = builderForValue.build(); + return this; + } + public Builder mergeNameIndex(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex value) { + if (result.hasNameIndex() && + result.nameIndex_ != net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.getDefaultInstance()) { + result.nameIndex_ = + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.newBuilder(result.nameIndex_).mergeFrom(value).buildPartial(); + } else { + result.nameIndex_ = value; + } + result.hasNameIndex = true; + return this; + } + public Builder clearNameIndex() { + result.hasNameIndex = false; + result.nameIndex_ = net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.getDefaultInstance(); + return this; + } + + // repeated .OsmAndPoiBox boxes = 6; + public java.util.List getBoxesList() { + return java.util.Collections.unmodifiableList(result.boxes_); + } + public int getBoxesCount() { + return result.getBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiBox getBoxes(int index) { + return result.getBoxes(index); + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.boxes_.set(index, value); + return this; + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder builderForValue) { + result.boxes_.set(index, builderForValue.build()); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndPoiBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(value); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder builderForValue) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(builderForValue.build()); + return this; + } + public Builder addAllBoxes( + java.lang.Iterable values) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.boxes_); + return this; + } + public Builder clearBoxes() { + result.boxes_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndPoiBoxData poiData = 9; + public java.util.List getPoiDataList() { + return java.util.Collections.unmodifiableList(result.poiData_); + } + public int getPoiDataCount() { + return result.getPoiDataCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxData getPoiData(int index) { + return result.getPoiData(index); + } + public Builder setPoiData(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBoxData value) { + if (value == null) { + throw new NullPointerException(); + } + result.poiData_.set(index, value); + return this; + } + public Builder setPoiData(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.Builder builderForValue) { + result.poiData_.set(index, builderForValue.build()); + return this; + } + public Builder addPoiData(net.osmand.binary.OsmandOdb.OsmAndPoiBoxData value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + result.poiData_.add(value); + return this; + } + public Builder addPoiData(net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.Builder builderForValue) { + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + result.poiData_.add(builderForValue.build()); + return this; + } + public Builder addAllPoiData( + java.lang.Iterable values) { + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + super.addAll(values, result.poiData_); + return this; + } + public Builder clearPoiData() { + result.poiData_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiIndex) + } + + static { + defaultInstance = new OsmAndPoiIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiIndex) + } + + public static final class OsmAndPoiNameIndex extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiNameIndex.newBuilder() to construct. + private OsmAndPoiNameIndex() { + initFields(); + } + private OsmAndPoiNameIndex(boolean noInit) {} + + private static final OsmAndPoiNameIndex defaultInstance; + public static OsmAndPoiNameIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiNameIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiNameIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiNameIndex_fieldAccessorTable; + } + + public static final class OsmAndPoiNameIndexData extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiNameIndexData.newBuilder() to construct. + private OsmAndPoiNameIndexData() { + initFields(); + } + private OsmAndPoiNameIndexData(boolean noInit) {} + + private static final OsmAndPoiNameIndexData defaultInstance; + public static OsmAndPoiNameIndexData getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiNameIndexData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_fieldAccessorTable; + } + + // repeated .OsmAndPoiNameIndexDataAtom atoms = 3; + public static final int ATOMS_FIELD_NUMBER = 3; + private java.util.List atoms_ = + java.util.Collections.emptyList(); + public java.util.List getAtomsList() { + return atoms_; + } + public int getAtomsCount() { return atoms_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom getAtoms(int index) { + return atoms_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom element : getAtomsList()) { + output.writeMessage(3, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + for (net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom element : getAtomsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.atoms_ != java.util.Collections.EMPTY_LIST) { + result.atoms_ = + java.util.Collections.unmodifiableList(result.atoms_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.getDefaultInstance()) return this; + if (!other.atoms_.isEmpty()) { + if (result.atoms_.isEmpty()) { + result.atoms_ = new java.util.ArrayList(); + } + result.atoms_.addAll(other.atoms_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 26: { + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addAtoms(subBuilder.buildPartial()); + break; + } + } + } + } + + + // repeated .OsmAndPoiNameIndexDataAtom atoms = 3; + public java.util.List getAtomsList() { + return java.util.Collections.unmodifiableList(result.atoms_); + } + public int getAtomsCount() { + return result.getAtomsCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom getAtoms(int index) { + return result.getAtoms(index); + } + public Builder setAtoms(int index, net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom value) { + if (value == null) { + throw new NullPointerException(); + } + result.atoms_.set(index, value); + return this; + } + public Builder setAtoms(int index, net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.Builder builderForValue) { + result.atoms_.set(index, builderForValue.build()); + return this; + } + public Builder addAtoms(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.atoms_.isEmpty()) { + result.atoms_ = new java.util.ArrayList(); + } + result.atoms_.add(value); + return this; + } + public Builder addAtoms(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.Builder builderForValue) { + if (result.atoms_.isEmpty()) { + result.atoms_ = new java.util.ArrayList(); + } + result.atoms_.add(builderForValue.build()); + return this; + } + public Builder addAllAtoms( + java.lang.Iterable values) { + if (result.atoms_.isEmpty()) { + result.atoms_ = new java.util.ArrayList(); + } + super.addAll(values, result.atoms_); + return this; + } + public Builder clearAtoms() { + result.atoms_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiNameIndex.OsmAndPoiNameIndexData) + } + + static { + defaultInstance = new OsmAndPoiNameIndexData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiNameIndex.OsmAndPoiNameIndexData) + } + + // required .IndexedStringTable table = 3; + public static final int TABLE_FIELD_NUMBER = 3; + private boolean hasTable; + private net.osmand.binary.OsmandOdb.IndexedStringTable table_; + public boolean hasTable() { return hasTable; } + public net.osmand.binary.OsmandOdb.IndexedStringTable getTable() { return table_; } + + // repeated .OsmAndPoiNameIndex.OsmAndPoiNameIndexData data = 5; + public static final int DATA_FIELD_NUMBER = 5; + private java.util.List data_ = + java.util.Collections.emptyList(); + public java.util.List getDataList() { + return data_; + } + public int getDataCount() { return data_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData getData(int index) { + return data_.get(index); + } + + private void initFields() { + table_ = net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasTable) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasTable()) { + output.writeMessage(3, getTable()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData element : getDataList()) { + output.writeMessage(5, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasTable()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getTable()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData element : getDataList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.data_ != java.util.Collections.EMPTY_LIST) { + result.data_ = + java.util.Collections.unmodifiableList(result.data_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.getDefaultInstance()) return this; + if (other.hasTable()) { + mergeTable(other.getTable()); + } + if (!other.data_.isEmpty()) { + if (result.data_.isEmpty()) { + result.data_ = new java.util.ArrayList(); + } + result.data_.addAll(other.data_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 26: { + net.osmand.binary.OsmandOdb.IndexedStringTable.Builder subBuilder = net.osmand.binary.OsmandOdb.IndexedStringTable.newBuilder(); + if (hasTable()) { + subBuilder.mergeFrom(getTable()); + } + input.readMessage(subBuilder, extensionRegistry); + setTable(subBuilder.buildPartial()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addData(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required .IndexedStringTable table = 3; + public boolean hasTable() { + return result.hasTable(); + } + public net.osmand.binary.OsmandOdb.IndexedStringTable getTable() { + return result.getTable(); + } + public Builder setTable(net.osmand.binary.OsmandOdb.IndexedStringTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTable = true; + result.table_ = value; + return this; + } + public Builder setTable(net.osmand.binary.OsmandOdb.IndexedStringTable.Builder builderForValue) { + result.hasTable = true; + result.table_ = builderForValue.build(); + return this; + } + public Builder mergeTable(net.osmand.binary.OsmandOdb.IndexedStringTable value) { + if (result.hasTable() && + result.table_ != net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance()) { + result.table_ = + net.osmand.binary.OsmandOdb.IndexedStringTable.newBuilder(result.table_).mergeFrom(value).buildPartial(); + } else { + result.table_ = value; + } + result.hasTable = true; + return this; + } + public Builder clearTable() { + result.hasTable = false; + result.table_ = net.osmand.binary.OsmandOdb.IndexedStringTable.getDefaultInstance(); + return this; + } + + // repeated .OsmAndPoiNameIndex.OsmAndPoiNameIndexData data = 5; + public java.util.List getDataList() { + return java.util.Collections.unmodifiableList(result.data_); + } + public int getDataCount() { + return result.getDataCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData getData(int index) { + return result.getData(index); + } + public Builder setData(int index, net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData value) { + if (value == null) { + throw new NullPointerException(); + } + result.data_.set(index, value); + return this; + } + public Builder setData(int index, net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.Builder builderForValue) { + result.data_.set(index, builderForValue.build()); + return this; + } + public Builder addData(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.data_.isEmpty()) { + result.data_ = new java.util.ArrayList(); + } + result.data_.add(value); + return this; + } + public Builder addData(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.Builder builderForValue) { + if (result.data_.isEmpty()) { + result.data_ = new java.util.ArrayList(); + } + result.data_.add(builderForValue.build()); + return this; + } + public Builder addAllData( + java.lang.Iterable values) { + if (result.data_.isEmpty()) { + result.data_ = new java.util.ArrayList(); + } + super.addAll(values, result.data_); + return this; + } + public Builder clearData() { + result.data_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiNameIndex) + } + + static { + defaultInstance = new OsmAndPoiNameIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiNameIndex) + } + + public static final class OsmAndPoiNameIndexDataAtom extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiNameIndexDataAtom.newBuilder() to construct. + private OsmAndPoiNameIndexDataAtom() { + initFields(); + } + private OsmAndPoiNameIndexDataAtom(boolean noInit) {} + + private static final OsmAndPoiNameIndexDataAtom defaultInstance; + public static OsmAndPoiNameIndexDataAtom getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiNameIndexDataAtom getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiNameIndexDataAtom_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiNameIndexDataAtom_fieldAccessorTable; + } + + // optional uint32 zoom = 2; + public static final int ZOOM_FIELD_NUMBER = 2; + private boolean hasZoom; + private int zoom_ = 0; + public boolean hasZoom() { return hasZoom; } + public int getZoom() { return zoom_; } + + // optional uint32 x = 3; + public static final int X_FIELD_NUMBER = 3; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // optional uint32 y = 4; + public static final int Y_FIELD_NUMBER = 4; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // optional fixed32 shiftTo = 14; + public static final int SHIFTTO_FIELD_NUMBER = 14; + private boolean hasShiftTo; + private int shiftTo_ = 0; + public boolean hasShiftTo() { return hasShiftTo; } + public int getShiftTo() { return shiftTo_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasZoom()) { + output.writeUInt32(2, getZoom()); + } + if (hasX()) { + output.writeUInt32(3, getX()); + } + if (hasY()) { + output.writeUInt32(4, getY()); + } + if (hasShiftTo()) { + output.writeFixed32(14, getShiftTo()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasZoom()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(2, getZoom()); + } + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(3, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(4, getY()); + } + if (hasShiftTo()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(14, getShiftTo()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.getDefaultInstance()) return this; + if (other.hasZoom()) { + setZoom(other.getZoom()); + } + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (other.hasShiftTo()) { + setShiftTo(other.getShiftTo()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 16: { + setZoom(input.readUInt32()); + break; + } + case 24: { + setX(input.readUInt32()); + break; + } + case 32: { + setY(input.readUInt32()); + break; + } + case 117: { + setShiftTo(input.readFixed32()); + break; + } + } + } + } + + + // optional uint32 zoom = 2; + public boolean hasZoom() { + return result.hasZoom(); + } + public int getZoom() { + return result.getZoom(); + } + public Builder setZoom(int value) { + result.hasZoom = true; + result.zoom_ = value; + return this; + } + public Builder clearZoom() { + result.hasZoom = false; + result.zoom_ = 0; + return this; + } + + // optional uint32 x = 3; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // optional uint32 y = 4; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // optional fixed32 shiftTo = 14; + public boolean hasShiftTo() { + return result.hasShiftTo(); + } + public int getShiftTo() { + return result.getShiftTo(); + } + public Builder setShiftTo(int value) { + result.hasShiftTo = true; + result.shiftTo_ = value; + return this; + } + public Builder clearShiftTo() { + result.hasShiftTo = false; + result.shiftTo_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiNameIndexDataAtom) + } + + static { + defaultInstance = new OsmAndPoiNameIndexDataAtom(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiNameIndexDataAtom) + } + + public static final class OsmAndCategoryTable extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndCategoryTable.newBuilder() to construct. + private OsmAndCategoryTable() { + initFields(); + } + private OsmAndCategoryTable(boolean noInit) {} + + private static final OsmAndCategoryTable defaultInstance; + public static OsmAndCategoryTable getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndCategoryTable getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndCategoryTable_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndCategoryTable_fieldAccessorTable; + } + + // required string category = 1; + public static final int CATEGORY_FIELD_NUMBER = 1; + private boolean hasCategory; + private java.lang.String category_ = ""; + public boolean hasCategory() { return hasCategory; } + public java.lang.String getCategory() { return category_; } + + // repeated string subcategories = 3; + public static final int SUBCATEGORIES_FIELD_NUMBER = 3; + private java.util.List subcategories_ = + java.util.Collections.emptyList(); + public java.util.List getSubcategoriesList() { + return subcategories_; + } + public int getSubcategoriesCount() { return subcategories_.size(); } + public java.lang.String getSubcategories(int index) { + return subcategories_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasCategory) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasCategory()) { + output.writeString(1, getCategory()); + } + for (java.lang.String element : getSubcategoriesList()) { + output.writeString(3, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasCategory()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getCategory()); + } + { + int dataSize = 0; + for (java.lang.String element : getSubcategoriesList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getSubcategoriesList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndCategoryTable parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndCategoryTable prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndCategoryTable result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndCategoryTable.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndCategoryTable(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndCategoryTable internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndCategoryTable(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndCategoryTable.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndCategoryTable getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndCategoryTable.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndCategoryTable build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndCategoryTable buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndCategoryTable buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.subcategories_ != java.util.Collections.EMPTY_LIST) { + result.subcategories_ = + java.util.Collections.unmodifiableList(result.subcategories_); + } + net.osmand.binary.OsmandOdb.OsmAndCategoryTable returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndCategoryTable) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndCategoryTable)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndCategoryTable other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndCategoryTable.getDefaultInstance()) return this; + if (other.hasCategory()) { + setCategory(other.getCategory()); + } + if (!other.subcategories_.isEmpty()) { + if (result.subcategories_.isEmpty()) { + result.subcategories_ = new java.util.ArrayList(); + } + result.subcategories_.addAll(other.subcategories_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setCategory(input.readString()); + break; + } + case 26: { + addSubcategories(input.readString()); + break; + } + } + } + } + + + // required string category = 1; + public boolean hasCategory() { + return result.hasCategory(); + } + public java.lang.String getCategory() { + return result.getCategory(); + } + public Builder setCategory(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasCategory = true; + result.category_ = value; + return this; + } + public Builder clearCategory() { + result.hasCategory = false; + result.category_ = getDefaultInstance().getCategory(); + return this; + } + + // repeated string subcategories = 3; + public java.util.List getSubcategoriesList() { + return java.util.Collections.unmodifiableList(result.subcategories_); + } + public int getSubcategoriesCount() { + return result.getSubcategoriesCount(); + } + public java.lang.String getSubcategories(int index) { + return result.getSubcategories(index); + } + public Builder setSubcategories(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.subcategories_.set(index, value); + return this; + } + public Builder addSubcategories(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.subcategories_.isEmpty()) { + result.subcategories_ = new java.util.ArrayList(); + } + result.subcategories_.add(value); + return this; + } + public Builder addAllSubcategories( + java.lang.Iterable values) { + if (result.subcategories_.isEmpty()) { + result.subcategories_ = new java.util.ArrayList(); + } + super.addAll(values, result.subcategories_); + return this; + } + public Builder clearSubcategories() { + result.subcategories_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndCategoryTable) + } + + static { + defaultInstance = new OsmAndCategoryTable(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndCategoryTable) + } + + public static final class OsmAndPoiBox extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiBox.newBuilder() to construct. + private OsmAndPoiBox() { + initFields(); + } + private OsmAndPoiBox(boolean noInit) {} + + private static final OsmAndPoiBox defaultInstance; + public static OsmAndPoiBox getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiBox getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiBox_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiBox_fieldAccessorTable; + } + + // required uint32 zoom = 1; + public static final int ZOOM_FIELD_NUMBER = 1; + private boolean hasZoom; + private int zoom_ = 0; + public boolean hasZoom() { return hasZoom; } + public int getZoom() { return zoom_; } + + // required sint32 left = 2; + public static final int LEFT_FIELD_NUMBER = 2; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required sint32 top = 3; + public static final int TOP_FIELD_NUMBER = 3; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // optional .OsmAndPoiCategories categories = 4; + public static final int CATEGORIES_FIELD_NUMBER = 4; + private boolean hasCategories; + private net.osmand.binary.OsmandOdb.OsmAndPoiCategories categories_; + public boolean hasCategories() { return hasCategories; } + public net.osmand.binary.OsmandOdb.OsmAndPoiCategories getCategories() { return categories_; } + + // repeated .OsmAndPoiBox subBoxes = 10; + public static final int SUBBOXES_FIELD_NUMBER = 10; + private java.util.List subBoxes_ = + java.util.Collections.emptyList(); + public java.util.List getSubBoxesList() { + return subBoxes_; + } + public int getSubBoxesCount() { return subBoxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiBox getSubBoxes(int index) { + return subBoxes_.get(index); + } + + // optional fixed32 shiftToData = 14; + public static final int SHIFTTODATA_FIELD_NUMBER = 14; + private boolean hasShiftToData; + private int shiftToData_ = 0; + public boolean hasShiftToData() { return hasShiftToData; } + public int getShiftToData() { return shiftToData_; } + + private void initFields() { + categories_ = net.osmand.binary.OsmandOdb.OsmAndPoiCategories.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasZoom) return false; + if (!hasLeft) return false; + if (!hasTop) return false; + for (net.osmand.binary.OsmandOdb.OsmAndPoiBox element : getSubBoxesList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasZoom()) { + output.writeUInt32(1, getZoom()); + } + if (hasLeft()) { + output.writeSInt32(2, getLeft()); + } + if (hasTop()) { + output.writeSInt32(3, getTop()); + } + if (hasCategories()) { + output.writeMessage(4, getCategories()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBox element : getSubBoxesList()) { + output.writeMessage(10, element); + } + if (hasShiftToData()) { + output.writeFixed32(14, getShiftToData()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasZoom()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, getZoom()); + } + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getLeft()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getTop()); + } + if (hasCategories()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getCategories()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBox element : getSubBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(10, element); + } + if (hasShiftToData()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(14, getShiftToData()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBox parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiBox prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiBox result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiBox.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiBox(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiBox internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiBox(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiBox.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBox getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiBox.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBox build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiBox buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBox buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.subBoxes_ != java.util.Collections.EMPTY_LIST) { + result.subBoxes_ = + java.util.Collections.unmodifiableList(result.subBoxes_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiBox returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiBox) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiBox)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiBox other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiBox.getDefaultInstance()) return this; + if (other.hasZoom()) { + setZoom(other.getZoom()); + } + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasCategories()) { + mergeCategories(other.getCategories()); + } + if (!other.subBoxes_.isEmpty()) { + if (result.subBoxes_.isEmpty()) { + result.subBoxes_ = new java.util.ArrayList(); + } + result.subBoxes_.addAll(other.subBoxes_); + } + if (other.hasShiftToData()) { + setShiftToData(other.getShiftToData()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setZoom(input.readUInt32()); + break; + } + case 16: { + setLeft(input.readSInt32()); + break; + } + case 24: { + setTop(input.readSInt32()); + break; + } + case 34: { + net.osmand.binary.OsmandOdb.OsmAndPoiCategories.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiCategories.newBuilder(); + if (hasCategories()) { + subBuilder.mergeFrom(getCategories()); + } + input.readMessage(subBuilder, extensionRegistry); + setCategories(subBuilder.buildPartial()); + break; + } + case 82: { + net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addSubBoxes(subBuilder.buildPartial()); + break; + } + case 117: { + setShiftToData(input.readFixed32()); + break; + } + } + } + } + + + // required uint32 zoom = 1; + public boolean hasZoom() { + return result.hasZoom(); + } + public int getZoom() { + return result.getZoom(); + } + public Builder setZoom(int value) { + result.hasZoom = true; + result.zoom_ = value; + return this; + } + public Builder clearZoom() { + result.hasZoom = false; + result.zoom_ = 0; + return this; + } + + // required sint32 left = 2; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required sint32 top = 3; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // optional .OsmAndPoiCategories categories = 4; + public boolean hasCategories() { + return result.hasCategories(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiCategories getCategories() { + return result.getCategories(); + } + public Builder setCategories(net.osmand.binary.OsmandOdb.OsmAndPoiCategories value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasCategories = true; + result.categories_ = value; + return this; + } + public Builder setCategories(net.osmand.binary.OsmandOdb.OsmAndPoiCategories.Builder builderForValue) { + result.hasCategories = true; + result.categories_ = builderForValue.build(); + return this; + } + public Builder mergeCategories(net.osmand.binary.OsmandOdb.OsmAndPoiCategories value) { + if (result.hasCategories() && + result.categories_ != net.osmand.binary.OsmandOdb.OsmAndPoiCategories.getDefaultInstance()) { + result.categories_ = + net.osmand.binary.OsmandOdb.OsmAndPoiCategories.newBuilder(result.categories_).mergeFrom(value).buildPartial(); + } else { + result.categories_ = value; + } + result.hasCategories = true; + return this; + } + public Builder clearCategories() { + result.hasCategories = false; + result.categories_ = net.osmand.binary.OsmandOdb.OsmAndPoiCategories.getDefaultInstance(); + return this; + } + + // repeated .OsmAndPoiBox subBoxes = 10; + public java.util.List getSubBoxesList() { + return java.util.Collections.unmodifiableList(result.subBoxes_); + } + public int getSubBoxesCount() { + return result.getSubBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiBox getSubBoxes(int index) { + return result.getSubBoxes(index); + } + public Builder setSubBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.subBoxes_.set(index, value); + return this; + } + public Builder setSubBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder builderForValue) { + result.subBoxes_.set(index, builderForValue.build()); + return this; + } + public Builder addSubBoxes(net.osmand.binary.OsmandOdb.OsmAndPoiBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.subBoxes_.isEmpty()) { + result.subBoxes_ = new java.util.ArrayList(); + } + result.subBoxes_.add(value); + return this; + } + public Builder addSubBoxes(net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder builderForValue) { + if (result.subBoxes_.isEmpty()) { + result.subBoxes_ = new java.util.ArrayList(); + } + result.subBoxes_.add(builderForValue.build()); + return this; + } + public Builder addAllSubBoxes( + java.lang.Iterable values) { + if (result.subBoxes_.isEmpty()) { + result.subBoxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.subBoxes_); + return this; + } + public Builder clearSubBoxes() { + result.subBoxes_ = java.util.Collections.emptyList(); + return this; + } + + // optional fixed32 shiftToData = 14; + public boolean hasShiftToData() { + return result.hasShiftToData(); + } + public int getShiftToData() { + return result.getShiftToData(); + } + public Builder setShiftToData(int value) { + result.hasShiftToData = true; + result.shiftToData_ = value; + return this; + } + public Builder clearShiftToData() { + result.hasShiftToData = false; + result.shiftToData_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiBox) + } + + static { + defaultInstance = new OsmAndPoiBox(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiBox) + } + + public static final class OsmAndPoiCategories extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiCategories.newBuilder() to construct. + private OsmAndPoiCategories() { + initFields(); + } + private OsmAndPoiCategories(boolean noInit) {} + + private static final OsmAndPoiCategories defaultInstance; + public static OsmAndPoiCategories getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiCategories getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiCategories_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiCategories_fieldAccessorTable; + } + + // repeated uint32 categories = 3; + public static final int CATEGORIES_FIELD_NUMBER = 3; + private java.util.List categories_ = + java.util.Collections.emptyList(); + public java.util.List getCategoriesList() { + return categories_; + } + public int getCategoriesCount() { return categories_.size(); } + public int getCategories(int index) { + return categories_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (int element : getCategoriesList()) { + output.writeUInt32(3, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (int element : getCategoriesList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeUInt32SizeNoTag(element); + } + size += dataSize; + size += 1 * getCategoriesList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiCategories parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiCategories prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiCategories result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiCategories.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiCategories(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiCategories internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiCategories(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiCategories.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiCategories getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiCategories.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiCategories build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiCategories buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiCategories buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.categories_ != java.util.Collections.EMPTY_LIST) { + result.categories_ = + java.util.Collections.unmodifiableList(result.categories_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiCategories returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiCategories) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiCategories)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiCategories other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiCategories.getDefaultInstance()) return this; + if (!other.categories_.isEmpty()) { + if (result.categories_.isEmpty()) { + result.categories_ = new java.util.ArrayList(); + } + result.categories_.addAll(other.categories_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 24: { + addCategories(input.readUInt32()); + break; + } + case 26: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addCategories(input.readUInt32()); + } + input.popLimit(limit); + break; + } + } + } + } + + + // repeated uint32 categories = 3; + public java.util.List getCategoriesList() { + return java.util.Collections.unmodifiableList(result.categories_); + } + public int getCategoriesCount() { + return result.getCategoriesCount(); + } + public int getCategories(int index) { + return result.getCategories(index); + } + public Builder setCategories(int index, int value) { + result.categories_.set(index, value); + return this; + } + public Builder addCategories(int value) { + if (result.categories_.isEmpty()) { + result.categories_ = new java.util.ArrayList(); + } + result.categories_.add(value); + return this; + } + public Builder addAllCategories( + java.lang.Iterable values) { + if (result.categories_.isEmpty()) { + result.categories_ = new java.util.ArrayList(); + } + super.addAll(values, result.categories_); + return this; + } + public Builder clearCategories() { + result.categories_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiCategories) + } + + static { + defaultInstance = new OsmAndPoiCategories(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiCategories) + } + + public static final class OsmAndPoiBoxData extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiBoxData.newBuilder() to construct. + private OsmAndPoiBoxData() { + initFields(); + } + private OsmAndPoiBoxData(boolean noInit) {} + + private static final OsmAndPoiBoxData defaultInstance; + public static OsmAndPoiBoxData getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiBoxData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiBoxData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiBoxData_fieldAccessorTable; + } + + // optional uint32 zoom = 1; + public static final int ZOOM_FIELD_NUMBER = 1; + private boolean hasZoom; + private int zoom_ = 0; + public boolean hasZoom() { return hasZoom; } + public int getZoom() { return zoom_; } + + // optional uint32 x = 2; + public static final int X_FIELD_NUMBER = 2; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // optional uint32 y = 3; + public static final int Y_FIELD_NUMBER = 3; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // repeated .OsmAndPoiBoxDataAtom poiData = 5; + public static final int POIDATA_FIELD_NUMBER = 5; + private java.util.List poiData_ = + java.util.Collections.emptyList(); + public java.util.List getPoiDataList() { + return poiData_; + } + public int getPoiDataCount() { return poiData_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom getPoiData(int index) { + return poiData_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + for (net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom element : getPoiDataList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasZoom()) { + output.writeUInt32(1, getZoom()); + } + if (hasX()) { + output.writeUInt32(2, getX()); + } + if (hasY()) { + output.writeUInt32(3, getY()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom element : getPoiDataList()) { + output.writeMessage(5, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasZoom()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, getZoom()); + } + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(2, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(3, getY()); + } + for (net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom element : getPoiDataList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiBoxData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiBoxData result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiBoxData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiBoxData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiBoxData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiBoxData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.poiData_ != java.util.Collections.EMPTY_LIST) { + result.poiData_ = + java.util.Collections.unmodifiableList(result.poiData_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiBoxData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiBoxData) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiBoxData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiBoxData other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.getDefaultInstance()) return this; + if (other.hasZoom()) { + setZoom(other.getZoom()); + } + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (!other.poiData_.isEmpty()) { + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + result.poiData_.addAll(other.poiData_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setZoom(input.readUInt32()); + break; + } + case 16: { + setX(input.readUInt32()); + break; + } + case 24: { + setY(input.readUInt32()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPoiData(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional uint32 zoom = 1; + public boolean hasZoom() { + return result.hasZoom(); + } + public int getZoom() { + return result.getZoom(); + } + public Builder setZoom(int value) { + result.hasZoom = true; + result.zoom_ = value; + return this; + } + public Builder clearZoom() { + result.hasZoom = false; + result.zoom_ = 0; + return this; + } + + // optional uint32 x = 2; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // optional uint32 y = 3; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // repeated .OsmAndPoiBoxDataAtom poiData = 5; + public java.util.List getPoiDataList() { + return java.util.Collections.unmodifiableList(result.poiData_); + } + public int getPoiDataCount() { + return result.getPoiDataCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom getPoiData(int index) { + return result.getPoiData(index); + } + public Builder setPoiData(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom value) { + if (value == null) { + throw new NullPointerException(); + } + result.poiData_.set(index, value); + return this; + } + public Builder setPoiData(int index, net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.Builder builderForValue) { + result.poiData_.set(index, builderForValue.build()); + return this; + } + public Builder addPoiData(net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + result.poiData_.add(value); + return this; + } + public Builder addPoiData(net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.Builder builderForValue) { + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + result.poiData_.add(builderForValue.build()); + return this; + } + public Builder addAllPoiData( + java.lang.Iterable values) { + if (result.poiData_.isEmpty()) { + result.poiData_ = new java.util.ArrayList(); + } + super.addAll(values, result.poiData_); + return this; + } + public Builder clearPoiData() { + result.poiData_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiBoxData) + } + + static { + defaultInstance = new OsmAndPoiBoxData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiBoxData) + } + + public static final class OsmAndPoiBoxDataAtom extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndPoiBoxDataAtom.newBuilder() to construct. + private OsmAndPoiBoxDataAtom() { + initFields(); + } + private OsmAndPoiBoxDataAtom(boolean noInit) {} + + private static final OsmAndPoiBoxDataAtom defaultInstance; + public static OsmAndPoiBoxDataAtom getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndPoiBoxDataAtom getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiBoxDataAtom_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndPoiBoxDataAtom_fieldAccessorTable; + } + + // required sint32 dx = 2; + public static final int DX_FIELD_NUMBER = 2; + private boolean hasDx; + private int dx_ = 0; + public boolean hasDx() { return hasDx; } + public int getDx() { return dx_; } + + // required sint32 dy = 3; + public static final int DY_FIELD_NUMBER = 3; + private boolean hasDy; + private int dy_ = 0; + public boolean hasDy() { return hasDy; } + public int getDy() { return dy_; } + + // repeated uint32 categories = 4; + public static final int CATEGORIES_FIELD_NUMBER = 4; + private java.util.List categories_ = + java.util.Collections.emptyList(); + public java.util.List getCategoriesList() { + return categories_; + } + public int getCategoriesCount() { return categories_.size(); } + public int getCategories(int index) { + return categories_.get(index); + } + + // optional string name = 6; + public static final int NAME_FIELD_NUMBER = 6; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // optional string nameEn = 7; + public static final int NAMEEN_FIELD_NUMBER = 7; + private boolean hasNameEn; + private java.lang.String nameEn_ = ""; + public boolean hasNameEn() { return hasNameEn; } + public java.lang.String getNameEn() { return nameEn_; } + + // optional uint64 id = 8; + public static final int ID_FIELD_NUMBER = 8; + private boolean hasId; + private long id_ = 0L; + public boolean hasId() { return hasId; } + public long getId() { return id_; } + + // optional string openingHours = 10; + public static final int OPENINGHOURS_FIELD_NUMBER = 10; + private boolean hasOpeningHours; + private java.lang.String openingHours_ = ""; + public boolean hasOpeningHours() { return hasOpeningHours; } + public java.lang.String getOpeningHours() { return openingHours_; } + + // optional string site = 11; + public static final int SITE_FIELD_NUMBER = 11; + private boolean hasSite; + private java.lang.String site_ = ""; + public boolean hasSite() { return hasSite; } + public java.lang.String getSite() { return site_; } + + // optional string phone = 12; + public static final int PHONE_FIELD_NUMBER = 12; + private boolean hasPhone; + private java.lang.String phone_ = ""; + public boolean hasPhone() { return hasPhone; } + public java.lang.String getPhone() { return phone_; } + + // optional string note = 13; + public static final int NOTE_FIELD_NUMBER = 13; + private boolean hasNote; + private java.lang.String note_ = ""; + public boolean hasNote() { return hasNote; } + public java.lang.String getNote() { return note_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasDx) return false; + if (!hasDy) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasDx()) { + output.writeSInt32(2, getDx()); + } + if (hasDy()) { + output.writeSInt32(3, getDy()); + } + for (int element : getCategoriesList()) { + output.writeUInt32(4, element); + } + if (hasName()) { + output.writeString(6, getName()); + } + if (hasNameEn()) { + output.writeString(7, getNameEn()); + } + if (hasId()) { + output.writeUInt64(8, getId()); + } + if (hasOpeningHours()) { + output.writeString(10, getOpeningHours()); + } + if (hasSite()) { + output.writeString(11, getSite()); + } + if (hasPhone()) { + output.writeString(12, getPhone()); + } + if (hasNote()) { + output.writeString(13, getNote()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasDx()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getDx()); + } + if (hasDy()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getDy()); + } + { + int dataSize = 0; + for (int element : getCategoriesList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeUInt32SizeNoTag(element); + } + size += dataSize; + size += 1 * getCategoriesList().size(); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(6, getName()); + } + if (hasNameEn()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(7, getNameEn()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(8, getId()); + } + if (hasOpeningHours()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(10, getOpeningHours()); + } + if (hasSite()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(11, getSite()); + } + if (hasPhone()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(12, getPhone()); + } + if (hasNote()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(13, getNote()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.categories_ != java.util.Collections.EMPTY_LIST) { + result.categories_ = + java.util.Collections.unmodifiableList(result.categories_); + } + net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.getDefaultInstance()) return this; + if (other.hasDx()) { + setDx(other.getDx()); + } + if (other.hasDy()) { + setDy(other.getDy()); + } + if (!other.categories_.isEmpty()) { + if (result.categories_.isEmpty()) { + result.categories_ = new java.util.ArrayList(); + } + result.categories_.addAll(other.categories_); + } + if (other.hasName()) { + setName(other.getName()); + } + if (other.hasNameEn()) { + setNameEn(other.getNameEn()); + } + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasOpeningHours()) { + setOpeningHours(other.getOpeningHours()); + } + if (other.hasSite()) { + setSite(other.getSite()); + } + if (other.hasPhone()) { + setPhone(other.getPhone()); + } + if (other.hasNote()) { + setNote(other.getNote()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 16: { + setDx(input.readSInt32()); + break; + } + case 24: { + setDy(input.readSInt32()); + break; + } + case 32: { + addCategories(input.readUInt32()); + break; + } + case 34: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addCategories(input.readUInt32()); + } + input.popLimit(limit); + break; + } + case 50: { + setName(input.readString()); + break; + } + case 58: { + setNameEn(input.readString()); + break; + } + case 64: { + setId(input.readUInt64()); + break; + } + case 82: { + setOpeningHours(input.readString()); + break; + } + case 90: { + setSite(input.readString()); + break; + } + case 98: { + setPhone(input.readString()); + break; + } + case 106: { + setNote(input.readString()); + break; + } + } + } + } + + + // required sint32 dx = 2; + public boolean hasDx() { + return result.hasDx(); + } + public int getDx() { + return result.getDx(); + } + public Builder setDx(int value) { + result.hasDx = true; + result.dx_ = value; + return this; + } + public Builder clearDx() { + result.hasDx = false; + result.dx_ = 0; + return this; + } + + // required sint32 dy = 3; + public boolean hasDy() { + return result.hasDy(); + } + public int getDy() { + return result.getDy(); + } + public Builder setDy(int value) { + result.hasDy = true; + result.dy_ = value; + return this; + } + public Builder clearDy() { + result.hasDy = false; + result.dy_ = 0; + return this; + } + + // repeated uint32 categories = 4; + public java.util.List getCategoriesList() { + return java.util.Collections.unmodifiableList(result.categories_); + } + public int getCategoriesCount() { + return result.getCategoriesCount(); + } + public int getCategories(int index) { + return result.getCategories(index); + } + public Builder setCategories(int index, int value) { + result.categories_.set(index, value); + return this; + } + public Builder addCategories(int value) { + if (result.categories_.isEmpty()) { + result.categories_ = new java.util.ArrayList(); + } + result.categories_.add(value); + return this; + } + public Builder addAllCategories( + java.lang.Iterable values) { + if (result.categories_.isEmpty()) { + result.categories_ = new java.util.ArrayList(); + } + super.addAll(values, result.categories_); + return this; + } + public Builder clearCategories() { + result.categories_ = java.util.Collections.emptyList(); + return this; + } + + // optional string name = 6; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // optional string nameEn = 7; + public boolean hasNameEn() { + return result.hasNameEn(); + } + public java.lang.String getNameEn() { + return result.getNameEn(); + } + public Builder setNameEn(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNameEn = true; + result.nameEn_ = value; + return this; + } + public Builder clearNameEn() { + result.hasNameEn = false; + result.nameEn_ = getDefaultInstance().getNameEn(); + return this; + } + + // optional uint64 id = 8; + public boolean hasId() { + return result.hasId(); + } + public long getId() { + return result.getId(); + } + public Builder setId(long value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0L; + return this; + } + + // optional string openingHours = 10; + public boolean hasOpeningHours() { + return result.hasOpeningHours(); + } + public java.lang.String getOpeningHours() { + return result.getOpeningHours(); + } + public Builder setOpeningHours(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasOpeningHours = true; + result.openingHours_ = value; + return this; + } + public Builder clearOpeningHours() { + result.hasOpeningHours = false; + result.openingHours_ = getDefaultInstance().getOpeningHours(); + return this; + } + + // optional string site = 11; + public boolean hasSite() { + return result.hasSite(); + } + public java.lang.String getSite() { + return result.getSite(); + } + public Builder setSite(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasSite = true; + result.site_ = value; + return this; + } + public Builder clearSite() { + result.hasSite = false; + result.site_ = getDefaultInstance().getSite(); + return this; + } + + // optional string phone = 12; + public boolean hasPhone() { + return result.hasPhone(); + } + public java.lang.String getPhone() { + return result.getPhone(); + } + public Builder setPhone(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPhone = true; + result.phone_ = value; + return this; + } + public Builder clearPhone() { + result.hasPhone = false; + result.phone_ = getDefaultInstance().getPhone(); + return this; + } + + // optional string note = 13; + public boolean hasNote() { + return result.hasNote(); + } + public java.lang.String getNote() { + return result.getNote(); + } + public Builder setNote(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasNote = true; + result.note_ = value; + return this; + } + public Builder clearNote() { + result.hasNote = false; + result.note_ = getDefaultInstance().getNote(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndPoiBoxDataAtom) + } + + static { + defaultInstance = new OsmAndPoiBoxDataAtom(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndPoiBoxDataAtom) + } + + public static final class IdTable extends + com.google.protobuf.GeneratedMessage { + // Use IdTable.newBuilder() to construct. + private IdTable() { + initFields(); + } + private IdTable(boolean noInit) {} + + private static final IdTable defaultInstance; + public static IdTable getDefaultInstance() { + return defaultInstance; + } + + @Override + public IdTable getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_IdTable_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_IdTable_fieldAccessorTable; + } + + // repeated sint64 routeId = 1; + public static final int ROUTEID_FIELD_NUMBER = 1; + private java.util.List routeId_ = + java.util.Collections.emptyList(); + public java.util.List getRouteIdList() { + return routeId_; + } + public int getRouteIdCount() { return routeId_.size(); } + public long getRouteId(int index) { + return routeId_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (long element : getRouteIdList()) { + output.writeSInt64(1, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + { + int dataSize = 0; + for (long element : getRouteIdList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeSInt64SizeNoTag(element); + } + size += dataSize; + size += 1 * getRouteIdList().size(); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.IdTable parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.IdTable parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.IdTable parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.IdTable prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.IdTable result; + + // Construct using net.osmand.binary.OsmandOdb.IdTable.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.IdTable(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.IdTable internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.IdTable(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.IdTable.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.IdTable getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.IdTable.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.IdTable build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.IdTable buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.IdTable buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.routeId_ != java.util.Collections.EMPTY_LIST) { + result.routeId_ = + java.util.Collections.unmodifiableList(result.routeId_); + } + net.osmand.binary.OsmandOdb.IdTable returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.IdTable) { + return mergeFrom((net.osmand.binary.OsmandOdb.IdTable)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.IdTable other) { + if (other == net.osmand.binary.OsmandOdb.IdTable.getDefaultInstance()) return this; + if (!other.routeId_.isEmpty()) { + if (result.routeId_.isEmpty()) { + result.routeId_ = new java.util.ArrayList(); + } + result.routeId_.addAll(other.routeId_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + addRouteId(input.readSInt64()); + break; + } + case 10: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addRouteId(input.readSInt64()); + } + input.popLimit(limit); + break; + } + } + } + } + + + // repeated sint64 routeId = 1; + public java.util.List getRouteIdList() { + return java.util.Collections.unmodifiableList(result.routeId_); + } + public int getRouteIdCount() { + return result.getRouteIdCount(); + } + public long getRouteId(int index) { + return result.getRouteId(index); + } + public Builder setRouteId(int index, long value) { + result.routeId_.set(index, value); + return this; + } + public Builder addRouteId(long value) { + if (result.routeId_.isEmpty()) { + result.routeId_ = new java.util.ArrayList(); + } + result.routeId_.add(value); + return this; + } + public Builder addAllRouteId( + java.lang.Iterable values) { + if (result.routeId_.isEmpty()) { + result.routeId_ = new java.util.ArrayList(); + } + super.addAll(values, result.routeId_); + return this; + } + public Builder clearRouteId() { + result.routeId_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:IdTable) + } + + static { + defaultInstance = new IdTable(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:IdTable) + } + + public static final class RestrictionData extends + com.google.protobuf.GeneratedMessage { + // Use RestrictionData.newBuilder() to construct. + private RestrictionData() { + initFields(); + } + private RestrictionData(boolean noInit) {} + + private static final RestrictionData defaultInstance; + public static RestrictionData getDefaultInstance() { + return defaultInstance; + } + + @Override + public RestrictionData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_RestrictionData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_RestrictionData_fieldAccessorTable; + } + + // required int32 type = 1; + public static final int TYPE_FIELD_NUMBER = 1; + private boolean hasType; + private int type_ = 0; + public boolean hasType() { return hasType; } + public int getType() { return type_; } + + // required int32 from = 2; + public static final int FROM_FIELD_NUMBER = 2; + private boolean hasFrom; + private int from_ = 0; + public boolean hasFrom() { return hasFrom; } + public int getFrom() { return from_; } + + // required int32 to = 3; + public static final int TO_FIELD_NUMBER = 3; + private boolean hasTo; + private int to_ = 0; + public boolean hasTo() { return hasTo; } + public int getTo() { return to_; } + + // optional int32 via = 4; + public static final int VIA_FIELD_NUMBER = 4; + private boolean hasVia; + private int via_ = 0; + public boolean hasVia() { return hasVia; } + public int getVia() { return via_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasType) return false; + if (!hasFrom) return false; + if (!hasTo) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasType()) { + output.writeInt32(1, getType()); + } + if (hasFrom()) { + output.writeInt32(2, getFrom()); + } + if (hasTo()) { + output.writeInt32(3, getTo()); + } + if (hasVia()) { + output.writeInt32(4, getVia()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasType()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, getType()); + } + if (hasFrom()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getFrom()); + } + if (hasTo()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, getTo()); + } + if (hasVia()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getVia()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RestrictionData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.RestrictionData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.RestrictionData result; + + // Construct using net.osmand.binary.OsmandOdb.RestrictionData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.RestrictionData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.RestrictionData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.RestrictionData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.RestrictionData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.RestrictionData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.RestrictionData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.RestrictionData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.RestrictionData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.RestrictionData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.RestrictionData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.RestrictionData) { + return mergeFrom((net.osmand.binary.OsmandOdb.RestrictionData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.RestrictionData other) { + if (other == net.osmand.binary.OsmandOdb.RestrictionData.getDefaultInstance()) return this; + if (other.hasType()) { + setType(other.getType()); + } + if (other.hasFrom()) { + setFrom(other.getFrom()); + } + if (other.hasTo()) { + setTo(other.getTo()); + } + if (other.hasVia()) { + setVia(other.getVia()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setType(input.readInt32()); + break; + } + case 16: { + setFrom(input.readInt32()); + break; + } + case 24: { + setTo(input.readInt32()); + break; + } + case 32: { + setVia(input.readInt32()); + break; + } + } + } + } + + + // required int32 type = 1; + public boolean hasType() { + return result.hasType(); + } + public int getType() { + return result.getType(); + } + public Builder setType(int value) { + result.hasType = true; + result.type_ = value; + return this; + } + public Builder clearType() { + result.hasType = false; + result.type_ = 0; + return this; + } + + // required int32 from = 2; + public boolean hasFrom() { + return result.hasFrom(); + } + public int getFrom() { + return result.getFrom(); + } + public Builder setFrom(int value) { + result.hasFrom = true; + result.from_ = value; + return this; + } + public Builder clearFrom() { + result.hasFrom = false; + result.from_ = 0; + return this; + } + + // required int32 to = 3; + public boolean hasTo() { + return result.hasTo(); + } + public int getTo() { + return result.getTo(); + } + public Builder setTo(int value) { + result.hasTo = true; + result.to_ = value; + return this; + } + public Builder clearTo() { + result.hasTo = false; + result.to_ = 0; + return this; + } + + // optional int32 via = 4; + public boolean hasVia() { + return result.hasVia(); + } + public int getVia() { + return result.getVia(); + } + public Builder setVia(int value) { + result.hasVia = true; + result.via_ = value; + return this; + } + public Builder clearVia() { + result.hasVia = false; + result.via_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:RestrictionData) + } + + static { + defaultInstance = new RestrictionData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:RestrictionData) + } + + public static final class RouteData extends + com.google.protobuf.GeneratedMessage { + // Use RouteData.newBuilder() to construct. + private RouteData() { + initFields(); + } + private RouteData(boolean noInit) {} + + private static final RouteData defaultInstance; + public static RouteData getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteData getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_RouteData_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_RouteData_fieldAccessorTable; + } + + // required bytes points = 1; + public static final int POINTS_FIELD_NUMBER = 1; + private boolean hasPoints; + private com.google.protobuf.ByteString points_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasPoints() { return hasPoints; } + public com.google.protobuf.ByteString getPoints() { return points_; } + + // optional bytes pointTypes = 4; + public static final int POINTTYPES_FIELD_NUMBER = 4; + private boolean hasPointTypes; + private com.google.protobuf.ByteString pointTypes_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasPointTypes() { return hasPointTypes; } + public com.google.protobuf.ByteString getPointTypes() { return pointTypes_; } + + // required bytes types = 7; + public static final int TYPES_FIELD_NUMBER = 7; + private boolean hasTypes; + private com.google.protobuf.ByteString types_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasTypes() { return hasTypes; } + public com.google.protobuf.ByteString getTypes() { return types_; } + + // required int32 routeId = 12; + public static final int ROUTEID_FIELD_NUMBER = 12; + private boolean hasRouteId; + private int routeId_ = 0; + public boolean hasRouteId() { return hasRouteId; } + public int getRouteId() { return routeId_; } + + // optional bytes stringNames = 14; + public static final int STRINGNAMES_FIELD_NUMBER = 14; + private boolean hasStringNames; + private com.google.protobuf.ByteString stringNames_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasStringNames() { return hasStringNames; } + public com.google.protobuf.ByteString getStringNames() { return stringNames_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasPoints) return false; + if (!hasTypes) return false; + if (!hasRouteId) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasPoints()) { + output.writeBytes(1, getPoints()); + } + if (hasPointTypes()) { + output.writeBytes(4, getPointTypes()); + } + if (hasTypes()) { + output.writeBytes(7, getTypes()); + } + if (hasRouteId()) { + output.writeInt32(12, getRouteId()); + } + if (hasStringNames()) { + output.writeBytes(14, getStringNames()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasPoints()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, getPoints()); + } + if (hasPointTypes()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(4, getPointTypes()); + } + if (hasTypes()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(7, getTypes()); + } + if (hasRouteId()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(12, getRouteId()); + } + if (hasStringNames()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(14, getStringNames()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.RouteData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.RouteData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.RouteData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.RouteData prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.RouteData result; + + // Construct using net.osmand.binary.OsmandOdb.RouteData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.RouteData(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.RouteData internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.RouteData(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.RouteData.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.RouteData getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.RouteData.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.RouteData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.RouteData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.RouteData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.RouteData returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.RouteData) { + return mergeFrom((net.osmand.binary.OsmandOdb.RouteData)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.RouteData other) { + if (other == net.osmand.binary.OsmandOdb.RouteData.getDefaultInstance()) return this; + if (other.hasPoints()) { + setPoints(other.getPoints()); + } + if (other.hasPointTypes()) { + setPointTypes(other.getPointTypes()); + } + if (other.hasTypes()) { + setTypes(other.getTypes()); + } + if (other.hasRouteId()) { + setRouteId(other.getRouteId()); + } + if (other.hasStringNames()) { + setStringNames(other.getStringNames()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setPoints(input.readBytes()); + break; + } + case 34: { + setPointTypes(input.readBytes()); + break; + } + case 58: { + setTypes(input.readBytes()); + break; + } + case 96: { + setRouteId(input.readInt32()); + break; + } + case 114: { + setStringNames(input.readBytes()); + break; + } + } + } + } + + + // required bytes points = 1; + public boolean hasPoints() { + return result.hasPoints(); + } + public com.google.protobuf.ByteString getPoints() { + return result.getPoints(); + } + public Builder setPoints(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPoints = true; + result.points_ = value; + return this; + } + public Builder clearPoints() { + result.hasPoints = false; + result.points_ = getDefaultInstance().getPoints(); + return this; + } + + // optional bytes pointTypes = 4; + public boolean hasPointTypes() { + return result.hasPointTypes(); + } + public com.google.protobuf.ByteString getPointTypes() { + return result.getPointTypes(); + } + public Builder setPointTypes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPointTypes = true; + result.pointTypes_ = value; + return this; + } + public Builder clearPointTypes() { + result.hasPointTypes = false; + result.pointTypes_ = getDefaultInstance().getPointTypes(); + return this; + } + + // required bytes types = 7; + public boolean hasTypes() { + return result.hasTypes(); + } + public com.google.protobuf.ByteString getTypes() { + return result.getTypes(); + } + public Builder setTypes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTypes = true; + result.types_ = value; + return this; + } + public Builder clearTypes() { + result.hasTypes = false; + result.types_ = getDefaultInstance().getTypes(); + return this; + } + + // required int32 routeId = 12; + public boolean hasRouteId() { + return result.hasRouteId(); + } + public int getRouteId() { + return result.getRouteId(); + } + public Builder setRouteId(int value) { + result.hasRouteId = true; + result.routeId_ = value; + return this; + } + public Builder clearRouteId() { + result.hasRouteId = false; + result.routeId_ = 0; + return this; + } + + // optional bytes stringNames = 14; + public boolean hasStringNames() { + return result.hasStringNames(); + } + public com.google.protobuf.ByteString getStringNames() { + return result.getStringNames(); + } + public Builder setStringNames(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasStringNames = true; + result.stringNames_ = value; + return this; + } + public Builder clearStringNames() { + result.hasStringNames = false; + result.stringNames_ = getDefaultInstance().getStringNames(); + return this; + } + + // @@protoc_insertion_point(builder_scope:RouteData) + } + + static { + defaultInstance = new RouteData(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:RouteData) + } + + public static final class OsmAndRoutingIndex extends + com.google.protobuf.GeneratedMessage { + // Use OsmAndRoutingIndex.newBuilder() to construct. + private OsmAndRoutingIndex() { + initFields(); + } + private OsmAndRoutingIndex(boolean noInit) {} + + private static final OsmAndRoutingIndex defaultInstance; + public static OsmAndRoutingIndex getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndRoutingIndex getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_fieldAccessorTable; + } + + public static final class RouteEncodingRule extends + com.google.protobuf.GeneratedMessage { + // Use RouteEncodingRule.newBuilder() to construct. + private RouteEncodingRule() { + initFields(); + } + private RouteEncodingRule(boolean noInit) {} + + private static final RouteEncodingRule defaultInstance; + public static RouteEncodingRule getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteEncodingRule getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteEncodingRule_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteEncodingRule_fieldAccessorTable; + } + + // required string tag = 3; + public static final int TAG_FIELD_NUMBER = 3; + private boolean hasTag; + private java.lang.String tag_ = ""; + public boolean hasTag() { return hasTag; } + public java.lang.String getTag() { return tag_; } + + // required string value = 5; + public static final int VALUE_FIELD_NUMBER = 5; + private boolean hasValue; + private java.lang.String value_ = ""; + public boolean hasValue() { return hasValue; } + public java.lang.String getValue() { return value_; } + + // optional uint32 id = 7; + public static final int ID_FIELD_NUMBER = 7; + private boolean hasId; + private int id_ = 0; + public boolean hasId() { return hasId; } + public int getId() { return id_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasTag) return false; + if (!hasValue) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasTag()) { + output.writeString(3, getTag()); + } + if (hasValue()) { + output.writeString(5, getValue()); + } + if (hasId()) { + output.writeUInt32(7, getId()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasTag()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(3, getTag()); + } + if (hasValue()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(5, getValue()); + } + if (hasId()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(7, getId()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.getDefaultInstance()) return this; + if (other.hasTag()) { + setTag(other.getTag()); + } + if (other.hasValue()) { + setValue(other.getValue()); + } + if (other.hasId()) { + setId(other.getId()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 26: { + setTag(input.readString()); + break; + } + case 42: { + setValue(input.readString()); + break; + } + case 56: { + setId(input.readUInt32()); + break; + } + } + } + } + + + // required string tag = 3; + public boolean hasTag() { + return result.hasTag(); + } + public java.lang.String getTag() { + return result.getTag(); + } + public Builder setTag(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTag = true; + result.tag_ = value; + return this; + } + public Builder clearTag() { + result.hasTag = false; + result.tag_ = getDefaultInstance().getTag(); + return this; + } + + // required string value = 5; + public boolean hasValue() { + return result.hasValue(); + } + public java.lang.String getValue() { + return result.getValue(); + } + public Builder setValue(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasValue = true; + result.value_ = value; + return this; + } + public Builder clearValue() { + result.hasValue = false; + result.value_ = getDefaultInstance().getValue(); + return this; + } + + // optional uint32 id = 7; + public boolean hasId() { + return result.hasId(); + } + public int getId() { + return result.getId(); + } + public Builder setId(int value) { + result.hasId = true; + result.id_ = value; + return this; + } + public Builder clearId() { + result.hasId = false; + result.id_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteEncodingRule) + } + + static { + defaultInstance = new RouteEncodingRule(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteEncodingRule) + } + + public static final class RouteDataBox extends + com.google.protobuf.GeneratedMessage { + // Use RouteDataBox.newBuilder() to construct. + private RouteDataBox() { + initFields(); + } + private RouteDataBox(boolean noInit) {} + + private static final RouteDataBox defaultInstance; + public static RouteDataBox getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteDataBox getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteDataBox_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteDataBox_fieldAccessorTable; + } + + // required sint32 left = 1; + public static final int LEFT_FIELD_NUMBER = 1; + private boolean hasLeft; + private int left_ = 0; + public boolean hasLeft() { return hasLeft; } + public int getLeft() { return left_; } + + // required sint32 right = 2; + public static final int RIGHT_FIELD_NUMBER = 2; + private boolean hasRight; + private int right_ = 0; + public boolean hasRight() { return hasRight; } + public int getRight() { return right_; } + + // required sint32 top = 3; + public static final int TOP_FIELD_NUMBER = 3; + private boolean hasTop; + private int top_ = 0; + public boolean hasTop() { return hasTop; } + public int getTop() { return top_; } + + // required sint32 bottom = 4; + public static final int BOTTOM_FIELD_NUMBER = 4; + private boolean hasBottom; + private int bottom_ = 0; + public boolean hasBottom() { return hasBottom; } + public int getBottom() { return bottom_; } + + // optional fixed32 shiftToData = 5; + public static final int SHIFTTODATA_FIELD_NUMBER = 5; + private boolean hasShiftToData; + private int shiftToData_ = 0; + public boolean hasShiftToData() { return hasShiftToData; } + public int getShiftToData() { return shiftToData_; } + + // repeated .OsmAndRoutingIndex.RouteDataBox boxes = 7; + public static final int BOXES_FIELD_NUMBER = 7; + private java.util.List boxes_ = + java.util.Collections.emptyList(); + public java.util.List getBoxesList() { + return boxes_; + } + public int getBoxesCount() { return boxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getBoxes(int index) { + return boxes_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasLeft) return false; + if (!hasRight) return false; + if (!hasTop) return false; + if (!hasBottom) return false; + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getBoxesList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasLeft()) { + output.writeSInt32(1, getLeft()); + } + if (hasRight()) { + output.writeSInt32(2, getRight()); + } + if (hasTop()) { + output.writeSInt32(3, getTop()); + } + if (hasBottom()) { + output.writeSInt32(4, getBottom()); + } + if (hasShiftToData()) { + output.writeFixed32(5, getShiftToData()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getBoxesList()) { + output.writeMessage(7, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLeft()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(1, getLeft()); + } + if (hasRight()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(2, getRight()); + } + if (hasTop()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(3, getTop()); + } + if (hasBottom()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt32Size(4, getBottom()); + } + if (hasShiftToData()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(5, getShiftToData()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.boxes_ != java.util.Collections.EMPTY_LIST) { + result.boxes_ = + java.util.Collections.unmodifiableList(result.boxes_); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.getDefaultInstance()) return this; + if (other.hasLeft()) { + setLeft(other.getLeft()); + } + if (other.hasRight()) { + setRight(other.getRight()); + } + if (other.hasTop()) { + setTop(other.getTop()); + } + if (other.hasBottom()) { + setBottom(other.getBottom()); + } + if (other.hasShiftToData()) { + setShiftToData(other.getShiftToData()); + } + if (!other.boxes_.isEmpty()) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.addAll(other.boxes_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setLeft(input.readSInt32()); + break; + } + case 16: { + setRight(input.readSInt32()); + break; + } + case 24: { + setTop(input.readSInt32()); + break; + } + case 32: { + setBottom(input.readSInt32()); + break; + } + case 45: { + setShiftToData(input.readFixed32()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBoxes(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required sint32 left = 1; + public boolean hasLeft() { + return result.hasLeft(); + } + public int getLeft() { + return result.getLeft(); + } + public Builder setLeft(int value) { + result.hasLeft = true; + result.left_ = value; + return this; + } + public Builder clearLeft() { + result.hasLeft = false; + result.left_ = 0; + return this; + } + + // required sint32 right = 2; + public boolean hasRight() { + return result.hasRight(); + } + public int getRight() { + return result.getRight(); + } + public Builder setRight(int value) { + result.hasRight = true; + result.right_ = value; + return this; + } + public Builder clearRight() { + result.hasRight = false; + result.right_ = 0; + return this; + } + + // required sint32 top = 3; + public boolean hasTop() { + return result.hasTop(); + } + public int getTop() { + return result.getTop(); + } + public Builder setTop(int value) { + result.hasTop = true; + result.top_ = value; + return this; + } + public Builder clearTop() { + result.hasTop = false; + result.top_ = 0; + return this; + } + + // required sint32 bottom = 4; + public boolean hasBottom() { + return result.hasBottom(); + } + public int getBottom() { + return result.getBottom(); + } + public Builder setBottom(int value) { + result.hasBottom = true; + result.bottom_ = value; + return this; + } + public Builder clearBottom() { + result.hasBottom = false; + result.bottom_ = 0; + return this; + } + + // optional fixed32 shiftToData = 5; + public boolean hasShiftToData() { + return result.hasShiftToData(); + } + public int getShiftToData() { + return result.getShiftToData(); + } + public Builder setShiftToData(int value) { + result.hasShiftToData = true; + result.shiftToData_ = value; + return this; + } + public Builder clearShiftToData() { + result.hasShiftToData = false; + result.shiftToData_ = 0; + return this; + } + + // repeated .OsmAndRoutingIndex.RouteDataBox boxes = 7; + public java.util.List getBoxesList() { + return java.util.Collections.unmodifiableList(result.boxes_); + } + public int getBoxesCount() { + return result.getBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getBoxes(int index) { + return result.getBoxes(index); + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.boxes_.set(index, value); + return this; + } + public Builder setBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder builderForValue) { + result.boxes_.set(index, builderForValue.build()); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(value); + return this; + } + public Builder addBoxes(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder builderForValue) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + result.boxes_.add(builderForValue.build()); + return this; + } + public Builder addAllBoxes( + java.lang.Iterable values) { + if (result.boxes_.isEmpty()) { + result.boxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.boxes_); + return this; + } + public Builder clearBoxes() { + result.boxes_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteDataBox) + } + + static { + defaultInstance = new RouteDataBox(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteDataBox) + } + + public static final class RouteDataBlock extends + com.google.protobuf.GeneratedMessage { + // Use RouteDataBlock.newBuilder() to construct. + private RouteDataBlock() { + initFields(); + } + private RouteDataBlock(boolean noInit) {} + + private static final RouteDataBlock defaultInstance; + public static RouteDataBlock getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteDataBlock getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteDataBlock_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteDataBlock_fieldAccessorTable; + } + + // optional .IdTable idTable = 5; + public static final int IDTABLE_FIELD_NUMBER = 5; + private boolean hasIdTable; + private net.osmand.binary.OsmandOdb.IdTable idTable_; + public boolean hasIdTable() { return hasIdTable; } + public net.osmand.binary.OsmandOdb.IdTable getIdTable() { return idTable_; } + + // optional .StringTable stringTable = 8; + public static final int STRINGTABLE_FIELD_NUMBER = 8; + private boolean hasStringTable; + private net.osmand.binary.OsmandOdb.StringTable stringTable_; + public boolean hasStringTable() { return hasStringTable; } + public net.osmand.binary.OsmandOdb.StringTable getStringTable() { return stringTable_; } + + // repeated .RouteData dataObjects = 6; + public static final int DATAOBJECTS_FIELD_NUMBER = 6; + private java.util.List dataObjects_ = + java.util.Collections.emptyList(); + public java.util.List getDataObjectsList() { + return dataObjects_; + } + public int getDataObjectsCount() { return dataObjects_.size(); } + public net.osmand.binary.OsmandOdb.RouteData getDataObjects(int index) { + return dataObjects_.get(index); + } + + // repeated .RestrictionData restrictions = 7; + public static final int RESTRICTIONS_FIELD_NUMBER = 7; + private java.util.List restrictions_ = + java.util.Collections.emptyList(); + public java.util.List getRestrictionsList() { + return restrictions_; + } + public int getRestrictionsCount() { return restrictions_.size(); } + public net.osmand.binary.OsmandOdb.RestrictionData getRestrictions(int index) { + return restrictions_.get(index); + } + + private void initFields() { + idTable_ = net.osmand.binary.OsmandOdb.IdTable.getDefaultInstance(); + stringTable_ = net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + for (net.osmand.binary.OsmandOdb.RouteData element : getDataObjectsList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.RestrictionData element : getRestrictionsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasIdTable()) { + output.writeMessage(5, getIdTable()); + } + for (net.osmand.binary.OsmandOdb.RouteData element : getDataObjectsList()) { + output.writeMessage(6, element); + } + for (net.osmand.binary.OsmandOdb.RestrictionData element : getRestrictionsList()) { + output.writeMessage(7, element); + } + if (hasStringTable()) { + output.writeMessage(8, getStringTable()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasIdTable()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, getIdTable()); + } + for (net.osmand.binary.OsmandOdb.RouteData element : getDataObjectsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + for (net.osmand.binary.OsmandOdb.RestrictionData element : getRestrictionsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + if (hasStringTable()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, getStringTable()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.dataObjects_ != java.util.Collections.EMPTY_LIST) { + result.dataObjects_ = + java.util.Collections.unmodifiableList(result.dataObjects_); + } + if (result.restrictions_ != java.util.Collections.EMPTY_LIST) { + result.restrictions_ = + java.util.Collections.unmodifiableList(result.restrictions_); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.getDefaultInstance()) return this; + if (other.hasIdTable()) { + mergeIdTable(other.getIdTable()); + } + if (other.hasStringTable()) { + mergeStringTable(other.getStringTable()); + } + if (!other.dataObjects_.isEmpty()) { + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + result.dataObjects_.addAll(other.dataObjects_); + } + if (!other.restrictions_.isEmpty()) { + if (result.restrictions_.isEmpty()) { + result.restrictions_ = new java.util.ArrayList(); + } + result.restrictions_.addAll(other.restrictions_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 42: { + net.osmand.binary.OsmandOdb.IdTable.Builder subBuilder = net.osmand.binary.OsmandOdb.IdTable.newBuilder(); + if (hasIdTable()) { + subBuilder.mergeFrom(getIdTable()); + } + input.readMessage(subBuilder, extensionRegistry); + setIdTable(subBuilder.buildPartial()); + break; + } + case 50: { + net.osmand.binary.OsmandOdb.RouteData.Builder subBuilder = net.osmand.binary.OsmandOdb.RouteData.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addDataObjects(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.RestrictionData.Builder subBuilder = net.osmand.binary.OsmandOdb.RestrictionData.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRestrictions(subBuilder.buildPartial()); + break; + } + case 66: { + net.osmand.binary.OsmandOdb.StringTable.Builder subBuilder = net.osmand.binary.OsmandOdb.StringTable.newBuilder(); + if (hasStringTable()) { + subBuilder.mergeFrom(getStringTable()); + } + input.readMessage(subBuilder, extensionRegistry); + setStringTable(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional .IdTable idTable = 5; + public boolean hasIdTable() { + return result.hasIdTable(); + } + public net.osmand.binary.OsmandOdb.IdTable getIdTable() { + return result.getIdTable(); + } + public Builder setIdTable(net.osmand.binary.OsmandOdb.IdTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasIdTable = true; + result.idTable_ = value; + return this; + } + public Builder setIdTable(net.osmand.binary.OsmandOdb.IdTable.Builder builderForValue) { + result.hasIdTable = true; + result.idTable_ = builderForValue.build(); + return this; + } + public Builder mergeIdTable(net.osmand.binary.OsmandOdb.IdTable value) { + if (result.hasIdTable() && + result.idTable_ != net.osmand.binary.OsmandOdb.IdTable.getDefaultInstance()) { + result.idTable_ = + net.osmand.binary.OsmandOdb.IdTable.newBuilder(result.idTable_).mergeFrom(value).buildPartial(); + } else { + result.idTable_ = value; + } + result.hasIdTable = true; + return this; + } + public Builder clearIdTable() { + result.hasIdTable = false; + result.idTable_ = net.osmand.binary.OsmandOdb.IdTable.getDefaultInstance(); + return this; + } + + // optional .StringTable stringTable = 8; + public boolean hasStringTable() { + return result.hasStringTable(); + } + public net.osmand.binary.OsmandOdb.StringTable getStringTable() { + return result.getStringTable(); + } + public Builder setStringTable(net.osmand.binary.OsmandOdb.StringTable value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasStringTable = true; + result.stringTable_ = value; + return this; + } + public Builder setStringTable(net.osmand.binary.OsmandOdb.StringTable.Builder builderForValue) { + result.hasStringTable = true; + result.stringTable_ = builderForValue.build(); + return this; + } + public Builder mergeStringTable(net.osmand.binary.OsmandOdb.StringTable value) { + if (result.hasStringTable() && + result.stringTable_ != net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance()) { + result.stringTable_ = + net.osmand.binary.OsmandOdb.StringTable.newBuilder(result.stringTable_).mergeFrom(value).buildPartial(); + } else { + result.stringTable_ = value; + } + result.hasStringTable = true; + return this; + } + public Builder clearStringTable() { + result.hasStringTable = false; + result.stringTable_ = net.osmand.binary.OsmandOdb.StringTable.getDefaultInstance(); + return this; + } + + // repeated .RouteData dataObjects = 6; + public java.util.List getDataObjectsList() { + return java.util.Collections.unmodifiableList(result.dataObjects_); + } + public int getDataObjectsCount() { + return result.getDataObjectsCount(); + } + public net.osmand.binary.OsmandOdb.RouteData getDataObjects(int index) { + return result.getDataObjects(index); + } + public Builder setDataObjects(int index, net.osmand.binary.OsmandOdb.RouteData value) { + if (value == null) { + throw new NullPointerException(); + } + result.dataObjects_.set(index, value); + return this; + } + public Builder setDataObjects(int index, net.osmand.binary.OsmandOdb.RouteData.Builder builderForValue) { + result.dataObjects_.set(index, builderForValue.build()); + return this; + } + public Builder addDataObjects(net.osmand.binary.OsmandOdb.RouteData value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + result.dataObjects_.add(value); + return this; + } + public Builder addDataObjects(net.osmand.binary.OsmandOdb.RouteData.Builder builderForValue) { + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + result.dataObjects_.add(builderForValue.build()); + return this; + } + public Builder addAllDataObjects( + java.lang.Iterable values) { + if (result.dataObjects_.isEmpty()) { + result.dataObjects_ = new java.util.ArrayList(); + } + super.addAll(values, result.dataObjects_); + return this; + } + public Builder clearDataObjects() { + result.dataObjects_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .RestrictionData restrictions = 7; + public java.util.List getRestrictionsList() { + return java.util.Collections.unmodifiableList(result.restrictions_); + } + public int getRestrictionsCount() { + return result.getRestrictionsCount(); + } + public net.osmand.binary.OsmandOdb.RestrictionData getRestrictions(int index) { + return result.getRestrictions(index); + } + public Builder setRestrictions(int index, net.osmand.binary.OsmandOdb.RestrictionData value) { + if (value == null) { + throw new NullPointerException(); + } + result.restrictions_.set(index, value); + return this; + } + public Builder setRestrictions(int index, net.osmand.binary.OsmandOdb.RestrictionData.Builder builderForValue) { + result.restrictions_.set(index, builderForValue.build()); + return this; + } + public Builder addRestrictions(net.osmand.binary.OsmandOdb.RestrictionData value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.restrictions_.isEmpty()) { + result.restrictions_ = new java.util.ArrayList(); + } + result.restrictions_.add(value); + return this; + } + public Builder addRestrictions(net.osmand.binary.OsmandOdb.RestrictionData.Builder builderForValue) { + if (result.restrictions_.isEmpty()) { + result.restrictions_ = new java.util.ArrayList(); + } + result.restrictions_.add(builderForValue.build()); + return this; + } + public Builder addAllRestrictions( + java.lang.Iterable values) { + if (result.restrictions_.isEmpty()) { + result.restrictions_ = new java.util.ArrayList(); + } + super.addAll(values, result.restrictions_); + return this; + } + public Builder clearRestrictions() { + result.restrictions_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteDataBlock) + } + + static { + defaultInstance = new RouteDataBlock(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteDataBlock) + } + + public static final class RouteBorderBox extends + com.google.protobuf.GeneratedMessage { + // Use RouteBorderBox.newBuilder() to construct. + private RouteBorderBox() { + initFields(); + } + private RouteBorderBox(boolean noInit) {} + + private static final RouteBorderBox defaultInstance; + public static RouteBorderBox getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteBorderBox getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderBox_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderBox_fieldAccessorTable; + } + + // required .OsmAndTileBox boundaries = 1; + public static final int BOUNDARIES_FIELD_NUMBER = 1; + private boolean hasBoundaries; + private net.osmand.binary.OsmandOdb.OsmAndTileBox boundaries_; + public boolean hasBoundaries() { return hasBoundaries; } + public net.osmand.binary.OsmandOdb.OsmAndTileBox getBoundaries() { return boundaries_; } + + // optional uint32 tileZoomToSplit = 2; + public static final int TILEZOOMTOSPLIT_FIELD_NUMBER = 2; + private boolean hasTileZoomToSplit; + private int tileZoomToSplit_ = 0; + public boolean hasTileZoomToSplit() { return hasTileZoomToSplit; } + public int getTileZoomToSplit() { return tileZoomToSplit_; } + + // repeated .OsmAndRoutingIndex.RouteBorderLine borderLines = 6; + public static final int BORDERLINES_FIELD_NUMBER = 6; + private java.util.List borderLines_ = + java.util.Collections.emptyList(); + public java.util.List getBorderLinesList() { + return borderLines_; + } + public int getBorderLinesCount() { return borderLines_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine getBorderLines(int index) { + return borderLines_.get(index); + } + + // repeated .OsmAndRoutingIndex.RouteBorderPointsBlock blocks = 7; + public static final int BLOCKS_FIELD_NUMBER = 7; + private java.util.List blocks_ = + java.util.Collections.emptyList(); + public java.util.List getBlocksList() { + return blocks_; + } + public int getBlocksCount() { return blocks_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock getBlocks(int index) { + return blocks_.get(index); + } + + private void initFields() { + boundaries_ = net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasBoundaries) return false; + if (!getBoundaries().isInitialized()) return false; + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine element : getBorderLinesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock element : getBlocksList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasBoundaries()) { + output.writeMessage(1, getBoundaries()); + } + if (hasTileZoomToSplit()) { + output.writeUInt32(2, getTileZoomToSplit()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine element : getBorderLinesList()) { + output.writeMessage(6, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock element : getBlocksList()) { + output.writeMessage(7, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasBoundaries()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getBoundaries()); + } + if (hasTileZoomToSplit()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(2, getTileZoomToSplit()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine element : getBorderLinesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock element : getBlocksList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.borderLines_ != java.util.Collections.EMPTY_LIST) { + result.borderLines_ = + java.util.Collections.unmodifiableList(result.borderLines_); + } + if (result.blocks_ != java.util.Collections.EMPTY_LIST) { + result.blocks_ = + java.util.Collections.unmodifiableList(result.blocks_); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance()) return this; + if (other.hasBoundaries()) { + mergeBoundaries(other.getBoundaries()); + } + if (other.hasTileZoomToSplit()) { + setTileZoomToSplit(other.getTileZoomToSplit()); + } + if (!other.borderLines_.isEmpty()) { + if (result.borderLines_.isEmpty()) { + result.borderLines_ = new java.util.ArrayList(); + } + result.borderLines_.addAll(other.borderLines_); + } + if (!other.blocks_.isEmpty()) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.addAll(other.blocks_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder(); + if (hasBoundaries()) { + subBuilder.mergeFrom(getBoundaries()); + } + input.readMessage(subBuilder, extensionRegistry); + setBoundaries(subBuilder.buildPartial()); + break; + } + case 16: { + setTileZoomToSplit(input.readUInt32()); + break; + } + case 50: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBorderLines(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBlocks(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required .OsmAndTileBox boundaries = 1; + public boolean hasBoundaries() { + return result.hasBoundaries(); + } + public net.osmand.binary.OsmandOdb.OsmAndTileBox getBoundaries() { + return result.getBoundaries(); + } + public Builder setBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasBoundaries = true; + result.boundaries_ = value; + return this; + } + public Builder setBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder builderForValue) { + result.hasBoundaries = true; + result.boundaries_ = builderForValue.build(); + return this; + } + public Builder mergeBoundaries(net.osmand.binary.OsmandOdb.OsmAndTileBox value) { + if (result.hasBoundaries() && + result.boundaries_ != net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance()) { + result.boundaries_ = + net.osmand.binary.OsmandOdb.OsmAndTileBox.newBuilder(result.boundaries_).mergeFrom(value).buildPartial(); + } else { + result.boundaries_ = value; + } + result.hasBoundaries = true; + return this; + } + public Builder clearBoundaries() { + result.hasBoundaries = false; + result.boundaries_ = net.osmand.binary.OsmandOdb.OsmAndTileBox.getDefaultInstance(); + return this; + } + + // optional uint32 tileZoomToSplit = 2; + public boolean hasTileZoomToSplit() { + return result.hasTileZoomToSplit(); + } + public int getTileZoomToSplit() { + return result.getTileZoomToSplit(); + } + public Builder setTileZoomToSplit(int value) { + result.hasTileZoomToSplit = true; + result.tileZoomToSplit_ = value; + return this; + } + public Builder clearTileZoomToSplit() { + result.hasTileZoomToSplit = false; + result.tileZoomToSplit_ = 0; + return this; + } + + // repeated .OsmAndRoutingIndex.RouteBorderLine borderLines = 6; + public java.util.List getBorderLinesList() { + return java.util.Collections.unmodifiableList(result.borderLines_); + } + public int getBorderLinesCount() { + return result.getBorderLinesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine getBorderLines(int index) { + return result.getBorderLines(index); + } + public Builder setBorderLines(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine value) { + if (value == null) { + throw new NullPointerException(); + } + result.borderLines_.set(index, value); + return this; + } + public Builder setBorderLines(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.Builder builderForValue) { + result.borderLines_.set(index, builderForValue.build()); + return this; + } + public Builder addBorderLines(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.borderLines_.isEmpty()) { + result.borderLines_ = new java.util.ArrayList(); + } + result.borderLines_.add(value); + return this; + } + public Builder addBorderLines(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.Builder builderForValue) { + if (result.borderLines_.isEmpty()) { + result.borderLines_ = new java.util.ArrayList(); + } + result.borderLines_.add(builderForValue.build()); + return this; + } + public Builder addAllBorderLines( + java.lang.Iterable values) { + if (result.borderLines_.isEmpty()) { + result.borderLines_ = new java.util.ArrayList(); + } + super.addAll(values, result.borderLines_); + return this; + } + public Builder clearBorderLines() { + result.borderLines_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndRoutingIndex.RouteBorderPointsBlock blocks = 7; + public java.util.List getBlocksList() { + return java.util.Collections.unmodifiableList(result.blocks_); + } + public int getBlocksCount() { + return result.getBlocksCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock getBlocks(int index) { + return result.getBlocks(index); + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock value) { + if (value == null) { + throw new NullPointerException(); + } + result.blocks_.set(index, value); + return this; + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.Builder builderForValue) { + result.blocks_.set(index, builderForValue.build()); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(value); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.Builder builderForValue) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(builderForValue.build()); + return this; + } + public Builder addAllBlocks( + java.lang.Iterable values) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + super.addAll(values, result.blocks_); + return this; + } + public Builder clearBlocks() { + result.blocks_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteBorderBox) + } + + static { + defaultInstance = new RouteBorderBox(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteBorderBox) + } + + public static final class RouteBorderLine extends + com.google.protobuf.GeneratedMessage { + // Use RouteBorderLine.newBuilder() to construct. + private RouteBorderLine() { + initFields(); + } + private RouteBorderLine(boolean noInit) {} + + private static final RouteBorderLine defaultInstance; + public static RouteBorderLine getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteBorderLine getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderLine_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderLine_fieldAccessorTable; + } + + // required int32 x = 1; + public static final int X_FIELD_NUMBER = 1; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // required int32 y = 2; + public static final int Y_FIELD_NUMBER = 2; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // optional int32 tox = 3; + public static final int TOX_FIELD_NUMBER = 3; + private boolean hasTox; + private int tox_ = 0; + public boolean hasTox() { return hasTox; } + public int getTox() { return tox_; } + + // optional int32 toy = 4; + public static final int TOY_FIELD_NUMBER = 4; + private boolean hasToy; + private int toy_ = 0; + public boolean hasToy() { return hasToy; } + public int getToy() { return toy_; } + + // required fixed32 shiftToPointsBlock = 7; + public static final int SHIFTTOPOINTSBLOCK_FIELD_NUMBER = 7; + private boolean hasShiftToPointsBlock; + private int shiftToPointsBlock_ = 0; + public boolean hasShiftToPointsBlock() { return hasShiftToPointsBlock; } + public int getShiftToPointsBlock() { return shiftToPointsBlock_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasX) return false; + if (!hasY) return false; + if (!hasShiftToPointsBlock) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasX()) { + output.writeInt32(1, getX()); + } + if (hasY()) { + output.writeInt32(2, getY()); + } + if (hasTox()) { + output.writeInt32(3, getTox()); + } + if (hasToy()) { + output.writeInt32(4, getToy()); + } + if (hasShiftToPointsBlock()) { + output.writeFixed32(7, getShiftToPointsBlock()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getY()); + } + if (hasTox()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, getTox()); + } + if (hasToy()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, getToy()); + } + if (hasShiftToPointsBlock()) { + size += com.google.protobuf.CodedOutputStream + .computeFixed32Size(7, getShiftToPointsBlock()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.getDefaultInstance()) return this; + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (other.hasTox()) { + setTox(other.getTox()); + } + if (other.hasToy()) { + setToy(other.getToy()); + } + if (other.hasShiftToPointsBlock()) { + setShiftToPointsBlock(other.getShiftToPointsBlock()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setX(input.readInt32()); + break; + } + case 16: { + setY(input.readInt32()); + break; + } + case 24: { + setTox(input.readInt32()); + break; + } + case 32: { + setToy(input.readInt32()); + break; + } + case 61: { + setShiftToPointsBlock(input.readFixed32()); + break; + } + } + } + } + + + // required int32 x = 1; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // required int32 y = 2; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // optional int32 tox = 3; + public boolean hasTox() { + return result.hasTox(); + } + public int getTox() { + return result.getTox(); + } + public Builder setTox(int value) { + result.hasTox = true; + result.tox_ = value; + return this; + } + public Builder clearTox() { + result.hasTox = false; + result.tox_ = 0; + return this; + } + + // optional int32 toy = 4; + public boolean hasToy() { + return result.hasToy(); + } + public int getToy() { + return result.getToy(); + } + public Builder setToy(int value) { + result.hasToy = true; + result.toy_ = value; + return this; + } + public Builder clearToy() { + result.hasToy = false; + result.toy_ = 0; + return this; + } + + // required fixed32 shiftToPointsBlock = 7; + public boolean hasShiftToPointsBlock() { + return result.hasShiftToPointsBlock(); + } + public int getShiftToPointsBlock() { + return result.getShiftToPointsBlock(); + } + public Builder setShiftToPointsBlock(int value) { + result.hasShiftToPointsBlock = true; + result.shiftToPointsBlock_ = value; + return this; + } + public Builder clearShiftToPointsBlock() { + result.hasShiftToPointsBlock = false; + result.shiftToPointsBlock_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteBorderLine) + } + + static { + defaultInstance = new RouteBorderLine(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteBorderLine) + } + + public static final class RouteBorderPointsBlock extends + com.google.protobuf.GeneratedMessage { + // Use RouteBorderPointsBlock.newBuilder() to construct. + private RouteBorderPointsBlock() { + initFields(); + } + private RouteBorderPointsBlock(boolean noInit) {} + + private static final RouteBorderPointsBlock defaultInstance; + public static RouteBorderPointsBlock getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteBorderPointsBlock getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_fieldAccessorTable; + } + + // required int32 x = 1; + public static final int X_FIELD_NUMBER = 1; + private boolean hasX; + private int x_ = 0; + public boolean hasX() { return hasX; } + public int getX() { return x_; } + + // required int32 y = 2; + public static final int Y_FIELD_NUMBER = 2; + private boolean hasY; + private int y_ = 0; + public boolean hasY() { return hasY; } + public int getY() { return y_; } + + // required int64 baseId = 3; + public static final int BASEID_FIELD_NUMBER = 3; + private boolean hasBaseId; + private long baseId_ = 0L; + public boolean hasBaseId() { return hasBaseId; } + public long getBaseId() { return baseId_; } + + // repeated .OsmAndRoutingIndex.RouteBorderPoint points = 5; + public static final int POINTS_FIELD_NUMBER = 5; + private java.util.List points_ = + java.util.Collections.emptyList(); + public java.util.List getPointsList() { + return points_; + } + public int getPointsCount() { return points_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint getPoints(int index) { + return points_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasX) return false; + if (!hasY) return false; + if (!hasBaseId) return false; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasX()) { + output.writeInt32(1, getX()); + } + if (hasY()) { + output.writeInt32(2, getY()); + } + if (hasBaseId()) { + output.writeInt64(3, getBaseId()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint element : getPointsList()) { + output.writeMessage(5, element); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasX()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, getX()); + } + if (hasY()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getY()); + } + if (hasBaseId()) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(3, getBaseId()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint element : getPointsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.points_ != java.util.Collections.EMPTY_LIST) { + result.points_ = + java.util.Collections.unmodifiableList(result.points_); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.getDefaultInstance()) return this; + if (other.hasX()) { + setX(other.getX()); + } + if (other.hasY()) { + setY(other.getY()); + } + if (other.hasBaseId()) { + setBaseId(other.getBaseId()); + } + if (!other.points_.isEmpty()) { + if (result.points_.isEmpty()) { + result.points_ = new java.util.ArrayList(); + } + result.points_.addAll(other.points_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setX(input.readInt32()); + break; + } + case 16: { + setY(input.readInt32()); + break; + } + case 24: { + setBaseId(input.readInt64()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addPoints(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required int32 x = 1; + public boolean hasX() { + return result.hasX(); + } + public int getX() { + return result.getX(); + } + public Builder setX(int value) { + result.hasX = true; + result.x_ = value; + return this; + } + public Builder clearX() { + result.hasX = false; + result.x_ = 0; + return this; + } + + // required int32 y = 2; + public boolean hasY() { + return result.hasY(); + } + public int getY() { + return result.getY(); + } + public Builder setY(int value) { + result.hasY = true; + result.y_ = value; + return this; + } + public Builder clearY() { + result.hasY = false; + result.y_ = 0; + return this; + } + + // required int64 baseId = 3; + public boolean hasBaseId() { + return result.hasBaseId(); + } + public long getBaseId() { + return result.getBaseId(); + } + public Builder setBaseId(long value) { + result.hasBaseId = true; + result.baseId_ = value; + return this; + } + public Builder clearBaseId() { + result.hasBaseId = false; + result.baseId_ = 0L; + return this; + } + + // repeated .OsmAndRoutingIndex.RouteBorderPoint points = 5; + public java.util.List getPointsList() { + return java.util.Collections.unmodifiableList(result.points_); + } + public int getPointsCount() { + return result.getPointsCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint getPoints(int index) { + return result.getPoints(index); + } + public Builder setPoints(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint value) { + if (value == null) { + throw new NullPointerException(); + } + result.points_.set(index, value); + return this; + } + public Builder setPoints(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.Builder builderForValue) { + result.points_.set(index, builderForValue.build()); + return this; + } + public Builder addPoints(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.points_.isEmpty()) { + result.points_ = new java.util.ArrayList(); + } + result.points_.add(value); + return this; + } + public Builder addPoints(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.Builder builderForValue) { + if (result.points_.isEmpty()) { + result.points_ = new java.util.ArrayList(); + } + result.points_.add(builderForValue.build()); + return this; + } + public Builder addAllPoints( + java.lang.Iterable values) { + if (result.points_.isEmpty()) { + result.points_ = new java.util.ArrayList(); + } + super.addAll(values, result.points_); + return this; + } + public Builder clearPoints() { + result.points_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteBorderPointsBlock) + } + + static { + defaultInstance = new RouteBorderPointsBlock(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteBorderPointsBlock) + } + + public static final class RouteBorderPoint extends + com.google.protobuf.GeneratedMessage { + // Use RouteBorderPoint.newBuilder() to construct. + private RouteBorderPoint() { + initFields(); + } + private RouteBorderPoint(boolean noInit) {} + + private static final RouteBorderPoint defaultInstance; + public static RouteBorderPoint getDefaultInstance() { + return defaultInstance; + } + + @Override + public RouteBorderPoint getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderPoint_descriptor; + } + + @Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return net.osmand.binary.OsmandOdb.internal_static_OsmAndRoutingIndex_RouteBorderPoint_fieldAccessorTable; + } + + // optional int32 dx = 1; + public static final int DX_FIELD_NUMBER = 1; + private boolean hasDx; + private int dx_ = 0; + public boolean hasDx() { return hasDx; } + public int getDx() { return dx_; } + + // optional int32 dy = 2; + public static final int DY_FIELD_NUMBER = 2; + private boolean hasDy; + private int dy_ = 0; + public boolean hasDy() { return hasDy; } + public int getDy() { return dy_; } + + // optional int32 direction = 3; + public static final int DIRECTION_FIELD_NUMBER = 3; + private boolean hasDirection; + private int direction_ = 0; + public boolean hasDirection() { return hasDirection; } + public int getDirection() { return direction_; } + + // optional bytes types = 4; + public static final int TYPES_FIELD_NUMBER = 4; + private boolean hasTypes; + private com.google.protobuf.ByteString types_ = com.google.protobuf.ByteString.EMPTY; + public boolean hasTypes() { return hasTypes; } + public com.google.protobuf.ByteString getTypes() { return types_; } + + // optional sint64 roadId = 7; + public static final int ROADID_FIELD_NUMBER = 7; + private boolean hasRoadId; + private long roadId_ = 0L; + public boolean hasRoadId() { return hasRoadId; } + public long getRoadId() { return roadId_; } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasDx()) { + output.writeInt32(1, getDx()); + } + if (hasDy()) { + output.writeInt32(2, getDy()); + } + if (hasDirection()) { + output.writeInt32(3, getDirection()); + } + if (hasTypes()) { + output.writeBytes(4, getTypes()); + } + if (hasRoadId()) { + output.writeSInt64(7, getRoadId()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasDx()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, getDx()); + } + if (hasDy()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getDy()); + } + if (hasDirection()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, getDirection()); + } + if (hasTypes()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(4, getTypes()); + } + if (hasRoadId()) { + size += com.google.protobuf.CodedOutputStream + .computeSInt64Size(7, getRoadId()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.getDefaultInstance()) return this; + if (other.hasDx()) { + setDx(other.getDx()); + } + if (other.hasDy()) { + setDy(other.getDy()); + } + if (other.hasDirection()) { + setDirection(other.getDirection()); + } + if (other.hasTypes()) { + setTypes(other.getTypes()); + } + if (other.hasRoadId()) { + setRoadId(other.getRoadId()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 8: { + setDx(input.readInt32()); + break; + } + case 16: { + setDy(input.readInt32()); + break; + } + case 24: { + setDirection(input.readInt32()); + break; + } + case 34: { + setTypes(input.readBytes()); + break; + } + case 56: { + setRoadId(input.readSInt64()); + break; + } + } + } + } + + + // optional int32 dx = 1; + public boolean hasDx() { + return result.hasDx(); + } + public int getDx() { + return result.getDx(); + } + public Builder setDx(int value) { + result.hasDx = true; + result.dx_ = value; + return this; + } + public Builder clearDx() { + result.hasDx = false; + result.dx_ = 0; + return this; + } + + // optional int32 dy = 2; + public boolean hasDy() { + return result.hasDy(); + } + public int getDy() { + return result.getDy(); + } + public Builder setDy(int value) { + result.hasDy = true; + result.dy_ = value; + return this; + } + public Builder clearDy() { + result.hasDy = false; + result.dy_ = 0; + return this; + } + + // optional int32 direction = 3; + public boolean hasDirection() { + return result.hasDirection(); + } + public int getDirection() { + return result.getDirection(); + } + public Builder setDirection(int value) { + result.hasDirection = true; + result.direction_ = value; + return this; + } + public Builder clearDirection() { + result.hasDirection = false; + result.direction_ = 0; + return this; + } + + // optional bytes types = 4; + public boolean hasTypes() { + return result.hasTypes(); + } + public com.google.protobuf.ByteString getTypes() { + return result.getTypes(); + } + public Builder setTypes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTypes = true; + result.types_ = value; + return this; + } + public Builder clearTypes() { + result.hasTypes = false; + result.types_ = getDefaultInstance().getTypes(); + return this; + } + + // optional sint64 roadId = 7; + public boolean hasRoadId() { + return result.hasRoadId(); + } + public long getRoadId() { + return result.getRoadId(); + } + public Builder setRoadId(long value) { + result.hasRoadId = true; + result.roadId_ = value; + return this; + } + public Builder clearRoadId() { + result.hasRoadId = false; + result.roadId_ = 0L; + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex.RouteBorderPoint) + } + + static { + defaultInstance = new RouteBorderPoint(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex.RouteBorderPoint) + } + + // required string name = 1; + public static final int NAME_FIELD_NUMBER = 1; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // repeated .OsmAndRoutingIndex.RouteEncodingRule rules = 2; + public static final int RULES_FIELD_NUMBER = 2; + private java.util.List rules_ = + java.util.Collections.emptyList(); + public java.util.List getRulesList() { + return rules_; + } + public int getRulesCount() { return rules_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule getRules(int index) { + return rules_.get(index); + } + + // repeated .OsmAndRoutingIndex.RouteDataBox rootBoxes = 3; + public static final int ROOTBOXES_FIELD_NUMBER = 3; + private java.util.List rootBoxes_ = + java.util.Collections.emptyList(); + public java.util.List getRootBoxesList() { + return rootBoxes_; + } + public int getRootBoxesCount() { return rootBoxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getRootBoxes(int index) { + return rootBoxes_.get(index); + } + + // repeated .OsmAndRoutingIndex.RouteDataBox basemapBoxes = 4; + public static final int BASEMAPBOXES_FIELD_NUMBER = 4; + private java.util.List basemapBoxes_ = + java.util.Collections.emptyList(); + public java.util.List getBasemapBoxesList() { + return basemapBoxes_; + } + public int getBasemapBoxesCount() { return basemapBoxes_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getBasemapBoxes(int index) { + return basemapBoxes_.get(index); + } + + // optional .OsmAndRoutingIndex.RouteBorderBox borderBox = 7; + public static final int BORDERBOX_FIELD_NUMBER = 7; + private boolean hasBorderBox; + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox borderBox_; + public boolean hasBorderBox() { return hasBorderBox; } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox getBorderBox() { return borderBox_; } + + // optional .OsmAndRoutingIndex.RouteBorderBox baseBorderBox = 8; + public static final int BASEBORDERBOX_FIELD_NUMBER = 8; + private boolean hasBaseBorderBox; + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox baseBorderBox_; + public boolean hasBaseBorderBox() { return hasBaseBorderBox; } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox getBaseBorderBox() { return baseBorderBox_; } + + // repeated .OsmAndRoutingIndex.RouteDataBlock blocks = 5; + public static final int BLOCKS_FIELD_NUMBER = 5; + private java.util.List blocks_ = + java.util.Collections.emptyList(); + public java.util.List getBlocksList() { + return blocks_; + } + public int getBlocksCount() { return blocks_.size(); } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock getBlocks(int index) { + return blocks_.get(index); + } + + private void initFields() { + borderBox_ = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance(); + baseBorderBox_ = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule element : getRulesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getRootBoxesList()) { + if (!element.isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getBasemapBoxesList()) { + if (!element.isInitialized()) return false; + } + if (hasBorderBox()) { + if (!getBorderBox().isInitialized()) return false; + } + if (hasBaseBorderBox()) { + if (!getBaseBorderBox().isInitialized()) return false; + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock element : getBlocksList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasName()) { + output.writeString(1, getName()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule element : getRulesList()) { + output.writeMessage(2, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getRootBoxesList()) { + output.writeMessage(3, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getBasemapBoxesList()) { + output.writeMessage(4, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock element : getBlocksList()) { + output.writeMessage(5, element); + } + if (hasBorderBox()) { + output.writeMessage(7, getBorderBox()); + } + if (hasBaseBorderBox()) { + output.writeMessage(8, getBaseBorderBox()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getName()); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule element : getRulesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getRootBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox element : getBasemapBoxesList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, element); + } + for (net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock element : getBlocksList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, element); + } + if (hasBorderBox()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, getBorderBox()); + } + if (hasBaseBorderBox()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, getBaseBorderBox()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.binary.OsmandOdb.OsmAndRoutingIndex parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex result; + + // Construct using net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex(); + return builder; + } + + @Override + protected net.osmand.binary.OsmandOdb.OsmAndRoutingIndex internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.binary.OsmandOdb.OsmAndRoutingIndex(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.getDescriptor(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex getDefaultInstanceForType() { + return net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.binary.OsmandOdb.OsmAndRoutingIndex buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.rules_ != java.util.Collections.EMPTY_LIST) { + result.rules_ = + java.util.Collections.unmodifiableList(result.rules_); + } + if (result.rootBoxes_ != java.util.Collections.EMPTY_LIST) { + result.rootBoxes_ = + java.util.Collections.unmodifiableList(result.rootBoxes_); + } + if (result.basemapBoxes_ != java.util.Collections.EMPTY_LIST) { + result.basemapBoxes_ = + java.util.Collections.unmodifiableList(result.basemapBoxes_); + } + if (result.blocks_ != java.util.Collections.EMPTY_LIST) { + result.blocks_ = + java.util.Collections.unmodifiableList(result.blocks_); + } + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof net.osmand.binary.OsmandOdb.OsmAndRoutingIndex) { + return mergeFrom((net.osmand.binary.OsmandOdb.OsmAndRoutingIndex)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex other) { + if (other == net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.getDefaultInstance()) return this; + if (other.hasName()) { + setName(other.getName()); + } + if (!other.rules_.isEmpty()) { + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + result.rules_.addAll(other.rules_); + } + if (!other.rootBoxes_.isEmpty()) { + if (result.rootBoxes_.isEmpty()) { + result.rootBoxes_ = new java.util.ArrayList(); + } + result.rootBoxes_.addAll(other.rootBoxes_); + } + if (!other.basemapBoxes_.isEmpty()) { + if (result.basemapBoxes_.isEmpty()) { + result.basemapBoxes_ = new java.util.ArrayList(); + } + result.basemapBoxes_.addAll(other.basemapBoxes_); + } + if (other.hasBorderBox()) { + mergeBorderBox(other.getBorderBox()); + } + if (other.hasBaseBorderBox()) { + mergeBaseBorderBox(other.getBaseBorderBox()); + } + if (!other.blocks_.isEmpty()) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.addAll(other.blocks_); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setName(input.readString()); + break; + } + case 18: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRules(subBuilder.buildPartial()); + break; + } + case 26: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRootBoxes(subBuilder.buildPartial()); + break; + } + case 34: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBasemapBoxes(subBuilder.buildPartial()); + break; + } + case 42: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addBlocks(subBuilder.buildPartial()); + break; + } + case 58: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.newBuilder(); + if (hasBorderBox()) { + subBuilder.mergeFrom(getBorderBox()); + } + input.readMessage(subBuilder, extensionRegistry); + setBorderBox(subBuilder.buildPartial()); + break; + } + case 66: { + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.Builder subBuilder = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.newBuilder(); + if (hasBaseBorderBox()) { + subBuilder.mergeFrom(getBaseBorderBox()); + } + input.readMessage(subBuilder, extensionRegistry); + setBaseBorderBox(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required string name = 1; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // repeated .OsmAndRoutingIndex.RouteEncodingRule rules = 2; + public java.util.List getRulesList() { + return java.util.Collections.unmodifiableList(result.rules_); + } + public int getRulesCount() { + return result.getRulesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule getRules(int index) { + return result.getRules(index); + } + public Builder setRules(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule value) { + if (value == null) { + throw new NullPointerException(); + } + result.rules_.set(index, value); + return this; + } + public Builder setRules(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.Builder builderForValue) { + result.rules_.set(index, builderForValue.build()); + return this; + } + public Builder addRules(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + result.rules_.add(value); + return this; + } + public Builder addRules(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.Builder builderForValue) { + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + result.rules_.add(builderForValue.build()); + return this; + } + public Builder addAllRules( + java.lang.Iterable values) { + if (result.rules_.isEmpty()) { + result.rules_ = new java.util.ArrayList(); + } + super.addAll(values, result.rules_); + return this; + } + public Builder clearRules() { + result.rules_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndRoutingIndex.RouteDataBox rootBoxes = 3; + public java.util.List getRootBoxesList() { + return java.util.Collections.unmodifiableList(result.rootBoxes_); + } + public int getRootBoxesCount() { + return result.getRootBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getRootBoxes(int index) { + return result.getRootBoxes(index); + } + public Builder setRootBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.rootBoxes_.set(index, value); + return this; + } + public Builder setRootBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder builderForValue) { + result.rootBoxes_.set(index, builderForValue.build()); + return this; + } + public Builder addRootBoxes(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.rootBoxes_.isEmpty()) { + result.rootBoxes_ = new java.util.ArrayList(); + } + result.rootBoxes_.add(value); + return this; + } + public Builder addRootBoxes(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder builderForValue) { + if (result.rootBoxes_.isEmpty()) { + result.rootBoxes_ = new java.util.ArrayList(); + } + result.rootBoxes_.add(builderForValue.build()); + return this; + } + public Builder addAllRootBoxes( + java.lang.Iterable values) { + if (result.rootBoxes_.isEmpty()) { + result.rootBoxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.rootBoxes_); + return this; + } + public Builder clearRootBoxes() { + result.rootBoxes_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndRoutingIndex.RouteDataBox basemapBoxes = 4; + public java.util.List getBasemapBoxesList() { + return java.util.Collections.unmodifiableList(result.basemapBoxes_); + } + public int getBasemapBoxesCount() { + return result.getBasemapBoxesCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox getBasemapBoxes(int index) { + return result.getBasemapBoxes(index); + } + public Builder setBasemapBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.basemapBoxes_.set(index, value); + return this; + } + public Builder setBasemapBoxes(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder builderForValue) { + result.basemapBoxes_.set(index, builderForValue.build()); + return this; + } + public Builder addBasemapBoxes(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.basemapBoxes_.isEmpty()) { + result.basemapBoxes_ = new java.util.ArrayList(); + } + result.basemapBoxes_.add(value); + return this; + } + public Builder addBasemapBoxes(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder builderForValue) { + if (result.basemapBoxes_.isEmpty()) { + result.basemapBoxes_ = new java.util.ArrayList(); + } + result.basemapBoxes_.add(builderForValue.build()); + return this; + } + public Builder addAllBasemapBoxes( + java.lang.Iterable values) { + if (result.basemapBoxes_.isEmpty()) { + result.basemapBoxes_ = new java.util.ArrayList(); + } + super.addAll(values, result.basemapBoxes_); + return this; + } + public Builder clearBasemapBoxes() { + result.basemapBoxes_ = java.util.Collections.emptyList(); + return this; + } + + // optional .OsmAndRoutingIndex.RouteBorderBox borderBox = 7; + public boolean hasBorderBox() { + return result.hasBorderBox(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox getBorderBox() { + return result.getBorderBox(); + } + public Builder setBorderBox(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasBorderBox = true; + result.borderBox_ = value; + return this; + } + public Builder setBorderBox(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.Builder builderForValue) { + result.hasBorderBox = true; + result.borderBox_ = builderForValue.build(); + return this; + } + public Builder mergeBorderBox(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox value) { + if (result.hasBorderBox() && + result.borderBox_ != net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance()) { + result.borderBox_ = + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.newBuilder(result.borderBox_).mergeFrom(value).buildPartial(); + } else { + result.borderBox_ = value; + } + result.hasBorderBox = true; + return this; + } + public Builder clearBorderBox() { + result.hasBorderBox = false; + result.borderBox_ = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance(); + return this; + } + + // optional .OsmAndRoutingIndex.RouteBorderBox baseBorderBox = 8; + public boolean hasBaseBorderBox() { + return result.hasBaseBorderBox(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox getBaseBorderBox() { + return result.getBaseBorderBox(); + } + public Builder setBaseBorderBox(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasBaseBorderBox = true; + result.baseBorderBox_ = value; + return this; + } + public Builder setBaseBorderBox(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.Builder builderForValue) { + result.hasBaseBorderBox = true; + result.baseBorderBox_ = builderForValue.build(); + return this; + } + public Builder mergeBaseBorderBox(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox value) { + if (result.hasBaseBorderBox() && + result.baseBorderBox_ != net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance()) { + result.baseBorderBox_ = + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.newBuilder(result.baseBorderBox_).mergeFrom(value).buildPartial(); + } else { + result.baseBorderBox_ = value; + } + result.hasBaseBorderBox = true; + return this; + } + public Builder clearBaseBorderBox() { + result.hasBaseBorderBox = false; + result.baseBorderBox_ = net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.getDefaultInstance(); + return this; + } + + // repeated .OsmAndRoutingIndex.RouteDataBlock blocks = 5; + public java.util.List getBlocksList() { + return java.util.Collections.unmodifiableList(result.blocks_); + } + public int getBlocksCount() { + return result.getBlocksCount(); + } + public net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock getBlocks(int index) { + return result.getBlocks(index); + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock value) { + if (value == null) { + throw new NullPointerException(); + } + result.blocks_.set(index, value); + return this; + } + public Builder setBlocks(int index, net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.Builder builderForValue) { + result.blocks_.set(index, builderForValue.build()); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(value); + return this; + } + public Builder addBlocks(net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.Builder builderForValue) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + result.blocks_.add(builderForValue.build()); + return this; + } + public Builder addAllBlocks( + java.lang.Iterable values) { + if (result.blocks_.isEmpty()) { + result.blocks_ = new java.util.ArrayList(); + } + super.addAll(values, result.blocks_); + return this; + } + public Builder clearBlocks() { + result.blocks_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRoutingIndex) + } + + static { + defaultInstance = new OsmAndRoutingIndex(true); + net.osmand.binary.OsmandOdb.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRoutingIndex) + } + + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndStructure_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndStructure_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndTileBox_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndTileBox_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_StringTable_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_StringTable_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_IndexedStringTable_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_IndexedStringTable_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndMapIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndMapIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndMapIndex_MapEncodingRule_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndMapIndex_MapEncodingRule_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndMapIndex_MapRootLevel_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndMapIndex_MapRootLevel_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndMapIndex_MapDataBox_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndMapIndex_MapDataBox_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_MapDataBlock_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_MapDataBlock_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_MapData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_MapData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndAddressIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndAddressIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndAddressIndex_CitiesIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndAddressIndex_CitiesIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndAddressNameIndexData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndAddressNameIndexData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_AddressNameIndexDataAtom_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_AddressNameIndexDataAtom_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_CityIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_CityIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_CityBlockIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_CityBlockIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_StreetIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_StreetIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_StreetIntersection_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_StreetIntersection_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_BuildingIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_BuildingIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_TransportRoutes_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_TransportRoutes_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_TransportRoute_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_TransportRoute_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_TransportRouteStop_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_TransportRouteStop_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_TransportStop_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_TransportStop_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_TransportStopsTree_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_TransportStopsTree_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndTransportIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndTransportIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiNameIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiNameIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiNameIndexDataAtom_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiNameIndexDataAtom_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndCategoryTable_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndCategoryTable_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiBox_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiBox_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiCategories_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiCategories_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiBoxData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiBoxData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndPoiBoxDataAtom_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndPoiBoxDataAtom_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_IdTable_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_IdTable_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_RestrictionData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_RestrictionData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_RouteData_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_RouteData_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteEncodingRule_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteEncodingRule_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteDataBox_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteDataBox_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteDataBlock_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteDataBlock_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteBorderBox_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteBorderBox_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteBorderLine_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteBorderLine_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_OsmAndRoutingIndex_RouteBorderPoint_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_OsmAndRoutingIndex_RouteBorderPoint_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n&DataExtractionOSM/src/osmand_odb.proto" + + "\"\232\002\n\017OsmAndStructure\022\017\n\007version\030\001 \002(\r\022\023\n" + + "\013dateCreated\030\022 \002(\003\022)\n\014addressIndex\030\007 \003(\013" + + "2\023.OsmAndAddressIndex\022-\n\016transportIndex\030" + + "\004 \003(\0132\025.OsmAndTransportIndex\022!\n\010poiIndex" + + "\030\010 \003(\0132\017.OsmAndPoiIndex\022!\n\010mapIndex\030\006 \003(" + + "\0132\017.OsmAndMapIndex\022)\n\014routingIndex\030\t \003(\013" + + "2\023.OsmAndRoutingIndex\022\026\n\016versionConfirm\030" + + " \002(\r\"I\n\rOsmAndTileBox\022\014\n\004left\030\001 \002(\r\022\r\n\005" + + "right\030\002 \002(\r\022\013\n\003top\030\003 \002(\r\022\016\n\006bottom\030\004 \002(\r", + "\"\030\n\013StringTable\022\t\n\001s\030\001 \003(\t\"f\n\022IndexedStr" + + "ingTable\022\016\n\006prefix\030\001 \001(\t\022\013\n\003key\030\003 \003(\t\022\013\n" + + "\003val\030\004 \003(\007\022&\n\tsubtables\030\005 \003(\0132\023.IndexedS" + + "tringTable\"\250\004\n\016OsmAndMapIndex\022\014\n\004name\030\002 " + + "\002(\t\022.\n\005rules\030\004 \003(\0132\037.OsmAndMapIndex.MapE" + + "ncodingRule\022,\n\006levels\030\005 \003(\0132\034.OsmAndMapI" + + "ndex.MapRootLevel\032X\n\017MapEncodingRule\022\013\n\003" + + "tag\030\003 \002(\t\022\r\n\005value\030\005 \001(\t\022\n\n\002id\030\007 \001(\r\022\017\n\007" + + "minZoom\030\t \001(\r\022\014\n\004type\030\n \001(\r\032\264\001\n\014MapRootL" + + "evel\022\017\n\007maxZoom\030\001 \002(\005\022\017\n\007minZoom\030\002 \002(\005\022\014", + "\n\004left\030\003 \002(\005\022\r\n\005right\030\004 \002(\005\022\013\n\003top\030\005 \002(\005" + + "\022\016\n\006bottom\030\006 \002(\005\022)\n\005boxes\030\007 \003(\0132\032.OsmAnd" + + "MapIndex.MapDataBox\022\035\n\006blocks\030\017 \003(\0132\r.Ma" + + "pDataBlock\032\230\001\n\nMapDataBox\022\014\n\004left\030\001 \002(\021\022" + + "\r\n\005right\030\002 \002(\021\022\013\n\003top\030\003 \002(\021\022\016\n\006bottom\030\004 " + + "\002(\021\022\026\n\016shiftToMapData\030\005 \001(\007\022\r\n\005ocean\030\006 \001" + + "(\010\022)\n\005boxes\030\007 \003(\0132\032.OsmAndMapIndex.MapDa" + + "taBox\"`\n\014MapDataBlock\022\016\n\006baseId\030\n \001(\004\022\035\n" + + "\013dataObjects\030\014 \003(\0132\010.MapData\022!\n\013stringTa" + + "ble\030\017 \001(\0132\014.StringTable\"\266\001\n\007MapData\022\023\n\013c", + "oordinates\030\001 \001(\014\022\027\n\017areaCoordinates\030\002 \001(" + + "\014\022\037\n\027polygonInnerCoordinates\030\004 \003(\014\022\027\n\017ad" + + "ditionalTypes\030\006 \001(\014\022\r\n\005types\030\007 \002(\014\022\023\n\013st" + + "ringNames\030\n \001(\014\022\n\n\002id\030\014 \002(\022\022\023\n\013rasterByt" + + "es\030\017 \001(\014\"\222\002\n\022OsmAndAddressIndex\022\014\n\004name\030" + + "\001 \002(\t\022\017\n\007name_en\030\002 \001(\t\022\"\n\nboundaries\030\003 \001" + + "(\0132\016.OsmAndTileBox\022/\n\006cities\030\006 \003(\0132\037.Osm" + + "AndAddressIndex.CitiesIndex\022.\n\tnameIndex" + + "\030\007 \001(\0132\033.OsmAndAddressNameIndexData\032X\n\013C" + + "itiesIndex\022\014\n\004type\030\002 \002(\r\022\032\n\006cities\030\005 \003(\013", + "2\n.CityIndex\022\037\n\006blocks\030\007 \003(\0132\017.CityBlock" + + "Index\"\301\001\n\032OsmAndAddressNameIndexData\022\"\n\005" + + "table\030\004 \002(\0132\023.IndexedStringTable\022>\n\004atom" + + "\030\007 \003(\01320.OsmAndAddressNameIndexData.Addr" + + "essNameIndexData\032?\n\024AddressNameIndexData" + + "\022\'\n\004atom\030\004 \003(\0132\031.AddressNameIndexDataAto" + + "m\"v\n\030AddressNameIndexDataAtom\022\014\n\004name\030\001 " + + "\001(\t\022\016\n\006nameEn\030\002 \001(\t\022\014\n\004type\030\003 \002(\r\022\024\n\014shi" + + "ftToIndex\030\005 \003(\005\022\030\n\020shiftToCityIndex\030\006 \003(" + + "\005\"~\n\tCityIndex\022\021\n\tcity_type\030\001 \001(\r\022\014\n\004nam", + "e\030\002 \002(\t\022\017\n\007name_en\030\003 \001(\t\022\n\n\002id\030\004 \001(\004\022\t\n\001" + + "x\030\005 \002(\r\022\t\n\001y\030\006 \002(\r\022\035\n\025shiftToCityBlockIn" + + "dex\030\n \001(\007\"l\n\016CityBlockIndex\022\030\n\020shiftToCi" + + "tyIndex\030\004 \001(\007\022!\n\tbuildings\030\n \003(\0132\016.Build" + + "ingIndex\022\035\n\007streets\030\014 \003(\0132\014.StreetIndex\"" + + "\235\001\n\013StreetIndex\022\014\n\004name\030\001 \002(\t\022\017\n\007name_en" + + "\030\002 \001(\t\022\t\n\001x\030\003 \002(\021\022\t\n\001y\030\004 \002(\021\022\n\n\002id\030\006 \001(\004" + + "\022!\n\tbuildings\030\014 \003(\0132\016.BuildingIndex\022*\n\ri" + + "ntersections\030\005 \003(\0132\023.StreetIntersection\"" + + "_\n\022StreetIntersection\022\014\n\004name\030\002 \002(\t\022\017\n\007n", + "ame_en\030\003 \001(\t\022\024\n\014intersectedX\030\004 \002(\021\022\024\n\014in" + + "tersectedY\030\005 \002(\021\"\262\001\n\rBuildingIndex\022\014\n\004na" + + "me\030\001 \002(\t\022\017\n\007name_en\030\002 \001(\t\022\r\n\005name2\030\003 \001(\t" + + "\022\020\n\010name_en2\030\004 \001(\t\022\025\n\rinterpolation\030\005 \001(" + + "\021\022\t\n\001x\030\007 \002(\021\022\t\n\001y\030\010 \002(\021\022\n\n\002x2\030\t \001(\021\022\n\n\002y" + + "2\030\n \001(\021\022\n\n\002id\030\r \001(\004\022\020\n\010postcode\030\016 \001(\t\"2\n" + + "\017TransportRoutes\022\037\n\006routes\030\006 \003(\0132\017.Trans" + + "portRoute\"\317\001\n\016TransportRoute\022\n\n\002id\030\001 \002(\004" + + "\022\014\n\004type\030\003 \001(\r\022\020\n\010operator\030\004 \001(\r\022\013\n\003ref\030" + + "\005 \001(\t\022\014\n\004name\030\006 \001(\r\022\017\n\007name_en\030\007 \001(\r\022\020\n\010", + "distance\030\010 \001(\r\022(\n\013directStops\030\017 \003(\0132\023.Tr" + + "ansportRouteStop\022)\n\014reverseStops\030\020 \003(\0132\023" + + ".TransportRouteStop\"W\n\022TransportRouteSto" + + "p\022\n\n\002id\030\001 \002(\022\022\n\n\002dx\030\002 \002(\021\022\n\n\002dy\030\003 \002(\021\022\014\n" + + "\004name\030\006 \002(\r\022\017\n\007name_en\030\007 \001(\r\"b\n\rTranspor" + + "tStop\022\n\n\002dx\030\001 \002(\021\022\n\n\002dy\030\002 \002(\021\022\n\n\002id\030\005 \002(" + + "\022\022\014\n\004name\030\006 \002(\r\022\017\n\007name_en\030\007 \001(\r\022\016\n\006rout" + + "es\030\020 \003(\r\"\244\001\n\022TransportStopsTree\022\014\n\004left\030" + + "\001 \002(\021\022\r\n\005right\030\002 \002(\021\022\013\n\003top\030\003 \002(\021\022\016\n\006bot" + + "tom\030\004 \002(\021\022%\n\010subtrees\030\007 \003(\0132\023.TransportS", + "topsTree\022\035\n\005leafs\030\010 \003(\0132\016.TransportStop\022" + + "\016\n\006baseId\030\020 \001(\004\"\215\001\n\024OsmAndTransportIndex" + + "\022\014\n\004name\030\001 \001(\t\022 \n\006routes\030\003 \001(\0132\020.Transpo" + + "rtRoutes\022\"\n\005stops\030\006 \001(\0132\023.TransportStops" + + "Tree\022!\n\013stringTable\030\t \002(\0132\014.StringTable\"" + + "\333\001\n\016OsmAndPoiIndex\022\014\n\004name\030\001 \002(\t\022\"\n\nboun" + + "daries\030\002 \002(\0132\016.OsmAndTileBox\022-\n\017categori" + + "esTable\030\003 \003(\0132\024.OsmAndCategoryTable\022&\n\tn" + + "ameIndex\030\004 \001(\0132\023.OsmAndPoiNameIndex\022\034\n\005b" + + "oxes\030\006 \003(\0132\r.OsmAndPoiBox\022\"\n\007poiData\030\t \003", + "(\0132\021.OsmAndPoiBoxData\"\270\001\n\022OsmAndPoiNameI" + + "ndex\022\"\n\005table\030\003 \002(\0132\023.IndexedStringTable" + + "\0228\n\004data\030\005 \003(\0132*.OsmAndPoiNameIndex.OsmA" + + "ndPoiNameIndexData\032D\n\026OsmAndPoiNameIndex" + + "Data\022*\n\005atoms\030\003 \003(\0132\033.OsmAndPoiNameIndex" + + "DataAtom\"Q\n\032OsmAndPoiNameIndexDataAtom\022\014" + + "\n\004zoom\030\002 \001(\r\022\t\n\001x\030\003 \001(\r\022\t\n\001y\030\004 \001(\r\022\017\n\007sh" + + "iftTo\030\016 \001(\007\">\n\023OsmAndCategoryTable\022\020\n\010ca" + + "tegory\030\001 \002(\t\022\025\n\rsubcategories\030\003 \003(\t\"\227\001\n\014" + + "OsmAndPoiBox\022\014\n\004zoom\030\001 \002(\r\022\014\n\004left\030\002 \002(\021", + "\022\013\n\003top\030\003 \002(\021\022(\n\ncategories\030\004 \001(\0132\024.OsmA" + + "ndPoiCategories\022\037\n\010subBoxes\030\n \003(\0132\r.OsmA" + + "ndPoiBox\022\023\n\013shiftToData\030\016 \001(\007\")\n\023OsmAndP" + + "oiCategories\022\022\n\ncategories\030\003 \003(\r\"^\n\020OsmA" + + "ndPoiBoxData\022\014\n\004zoom\030\001 \001(\r\022\t\n\001x\030\002 \001(\r\022\t\n" + + "\001y\030\003 \001(\r\022&\n\007poiData\030\005 \003(\0132\025.OsmAndPoiBox" + + "DataAtom\"\255\001\n\024OsmAndPoiBoxDataAtom\022\n\n\002dx\030" + + "\002 \002(\021\022\n\n\002dy\030\003 \002(\021\022\022\n\ncategories\030\004 \003(\r\022\014\n" + + "\004name\030\006 \001(\t\022\016\n\006nameEn\030\007 \001(\t\022\n\n\002id\030\010 \001(\004\022" + + "\024\n\014openingHours\030\n \001(\t\022\014\n\004site\030\013 \001(\t\022\r\n\005p", + "hone\030\014 \001(\t\022\014\n\004note\030\r \001(\t\"\032\n\007IdTable\022\017\n\007r" + + "outeId\030\001 \003(\022\"F\n\017RestrictionData\022\014\n\004type\030" + + "\001 \002(\005\022\014\n\004from\030\002 \002(\005\022\n\n\002to\030\003 \002(\005\022\013\n\003via\030\004" + + " \001(\005\"d\n\tRouteData\022\016\n\006points\030\001 \002(\014\022\022\n\npoi" + + "ntTypes\030\004 \001(\014\022\r\n\005types\030\007 \002(\014\022\017\n\007routeId\030" + + "\014 \002(\005\022\023\n\013stringNames\030\016 \001(\014\"\314\t\n\022OsmAndRou" + + "tingIndex\022\014\n\004name\030\001 \002(\t\0224\n\005rules\030\002 \003(\0132%" + + ".OsmAndRoutingIndex.RouteEncodingRule\0223\n" + + "\trootBoxes\030\003 \003(\0132 .OsmAndRoutingIndex.Ro" + + "uteDataBox\0226\n\014basemapBoxes\030\004 \003(\0132 .OsmAn", + "dRoutingIndex.RouteDataBox\0225\n\tborderBox\030" + + "\007 \001(\0132\".OsmAndRoutingIndex.RouteBorderBo" + + "x\0229\n\rbaseBorderBox\030\010 \001(\0132\".OsmAndRouting" + + "Index.RouteBorderBox\0222\n\006blocks\030\005 \003(\0132\".O" + + "smAndRoutingIndex.RouteDataBlock\032;\n\021Rout" + + "eEncodingRule\022\013\n\003tag\030\003 \002(\t\022\r\n\005value\030\005 \002(" + + "\t\022\n\n\002id\030\007 \001(\r\032\216\001\n\014RouteDataBox\022\014\n\004left\030\001" + + " \002(\021\022\r\n\005right\030\002 \002(\021\022\013\n\003top\030\003 \002(\021\022\016\n\006bott" + + "om\030\004 \002(\021\022\023\n\013shiftToData\030\005 \001(\007\022/\n\005boxes\030\007" + + " \003(\0132 .OsmAndRoutingIndex.RouteDataBox\032\227", + "\001\n\016RouteDataBlock\022\031\n\007idTable\030\005 \001(\0132\010.IdT" + + "able\022!\n\013stringTable\030\010 \001(\0132\014.StringTable\022" + + "\037\n\013dataObjects\030\006 \003(\0132\n.RouteData\022&\n\014rest" + + "rictions\030\007 \003(\0132\020.RestrictionData\032\303\001\n\016Rou" + + "teBorderBox\022\"\n\nboundaries\030\001 \002(\0132\016.OsmAnd" + + "TileBox\022\027\n\017tileZoomToSplit\030\002 \001(\r\0228\n\013bord" + + "erLines\030\006 \003(\0132#.OsmAndRoutingIndex.Route" + + "BorderLine\022:\n\006blocks\030\007 \003(\0132*.OsmAndRouti" + + "ngIndex.RouteBorderPointsBlock\032]\n\017RouteB" + + "orderLine\022\t\n\001x\030\001 \002(\005\022\t\n\001y\030\002 \002(\005\022\013\n\003tox\030\003", + " \001(\005\022\013\n\003toy\030\004 \001(\005\022\032\n\022shiftToPointsBlock\030" + + "\007 \002(\007\032t\n\026RouteBorderPointsBlock\022\t\n\001x\030\001 \002" + + "(\005\022\t\n\001y\030\002 \002(\005\022\016\n\006baseId\030\003 \002(\003\0224\n\006points\030" + + "\005 \003(\0132$.OsmAndRoutingIndex.RouteBorderPo" + + "int\032\\\n\020RouteBorderPoint\022\n\n\002dx\030\001 \001(\005\022\n\n\002d" + + "y\030\002 \001(\005\022\021\n\tdirection\030\003 \001(\005\022\r\n\005types\030\004 \001(" + + "\014\022\016\n\006roadId\030\007 \001(\022B\023\n\021net.osmand.binary" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { + @Override + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + internal_static_OsmAndStructure_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_OsmAndStructure_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndStructure_descriptor, + new java.lang.String[] { "Version", "DateCreated", "AddressIndex", "TransportIndex", "PoiIndex", "MapIndex", "RoutingIndex", "VersionConfirm", }, + net.osmand.binary.OsmandOdb.OsmAndStructure.class, + net.osmand.binary.OsmandOdb.OsmAndStructure.Builder.class); + internal_static_OsmAndTileBox_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_OsmAndTileBox_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndTileBox_descriptor, + new java.lang.String[] { "Left", "Right", "Top", "Bottom", }, + net.osmand.binary.OsmandOdb.OsmAndTileBox.class, + net.osmand.binary.OsmandOdb.OsmAndTileBox.Builder.class); + internal_static_StringTable_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_StringTable_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_StringTable_descriptor, + new java.lang.String[] { "S", }, + net.osmand.binary.OsmandOdb.StringTable.class, + net.osmand.binary.OsmandOdb.StringTable.Builder.class); + internal_static_IndexedStringTable_descriptor = + getDescriptor().getMessageTypes().get(3); + internal_static_IndexedStringTable_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_IndexedStringTable_descriptor, + new java.lang.String[] { "Prefix", "Key", "Val", "Subtables", }, + net.osmand.binary.OsmandOdb.IndexedStringTable.class, + net.osmand.binary.OsmandOdb.IndexedStringTable.Builder.class); + internal_static_OsmAndMapIndex_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_OsmAndMapIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndMapIndex_descriptor, + new java.lang.String[] { "Name", "Rules", "Levels", }, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.class, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.Builder.class); + internal_static_OsmAndMapIndex_MapEncodingRule_descriptor = + internal_static_OsmAndMapIndex_descriptor.getNestedTypes().get(0); + internal_static_OsmAndMapIndex_MapEncodingRule_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndMapIndex_MapEncodingRule_descriptor, + new java.lang.String[] { "Tag", "Value", "Id", "MinZoom", "Type", }, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.class, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapEncodingRule.Builder.class); + internal_static_OsmAndMapIndex_MapRootLevel_descriptor = + internal_static_OsmAndMapIndex_descriptor.getNestedTypes().get(1); + internal_static_OsmAndMapIndex_MapRootLevel_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndMapIndex_MapRootLevel_descriptor, + new java.lang.String[] { "MaxZoom", "MinZoom", "Left", "Right", "Top", "Bottom", "Boxes", "Blocks", }, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.class, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapRootLevel.Builder.class); + internal_static_OsmAndMapIndex_MapDataBox_descriptor = + internal_static_OsmAndMapIndex_descriptor.getNestedTypes().get(2); + internal_static_OsmAndMapIndex_MapDataBox_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndMapIndex_MapDataBox_descriptor, + new java.lang.String[] { "Left", "Right", "Top", "Bottom", "ShiftToMapData", "Ocean", "Boxes", }, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.class, + net.osmand.binary.OsmandOdb.OsmAndMapIndex.MapDataBox.Builder.class); + internal_static_MapDataBlock_descriptor = + getDescriptor().getMessageTypes().get(5); + internal_static_MapDataBlock_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_MapDataBlock_descriptor, + new java.lang.String[] { "BaseId", "DataObjects", "StringTable", }, + net.osmand.binary.OsmandOdb.MapDataBlock.class, + net.osmand.binary.OsmandOdb.MapDataBlock.Builder.class); + internal_static_MapData_descriptor = + getDescriptor().getMessageTypes().get(6); + internal_static_MapData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_MapData_descriptor, + new java.lang.String[] { "Coordinates", "AreaCoordinates", "PolygonInnerCoordinates", "AdditionalTypes", "Types", "StringNames", "Id", "RasterBytes", }, + net.osmand.binary.OsmandOdb.MapData.class, + net.osmand.binary.OsmandOdb.MapData.Builder.class); + internal_static_OsmAndAddressIndex_descriptor = + getDescriptor().getMessageTypes().get(7); + internal_static_OsmAndAddressIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndAddressIndex_descriptor, + new java.lang.String[] { "Name", "NameEn", "Boundaries", "Cities", "NameIndex", }, + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.class, + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.Builder.class); + internal_static_OsmAndAddressIndex_CitiesIndex_descriptor = + internal_static_OsmAndAddressIndex_descriptor.getNestedTypes().get(0); + internal_static_OsmAndAddressIndex_CitiesIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndAddressIndex_CitiesIndex_descriptor, + new java.lang.String[] { "Type", "Cities", "Blocks", }, + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.class, + net.osmand.binary.OsmandOdb.OsmAndAddressIndex.CitiesIndex.Builder.class); + internal_static_OsmAndAddressNameIndexData_descriptor = + getDescriptor().getMessageTypes().get(8); + internal_static_OsmAndAddressNameIndexData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndAddressNameIndexData_descriptor, + new java.lang.String[] { "Table", "Atom", }, + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.class, + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.Builder.class); + internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_descriptor = + internal_static_OsmAndAddressNameIndexData_descriptor.getNestedTypes().get(0); + internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndAddressNameIndexData_AddressNameIndexData_descriptor, + new java.lang.String[] { "Atom", }, + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.class, + net.osmand.binary.OsmandOdb.OsmAndAddressNameIndexData.AddressNameIndexData.Builder.class); + internal_static_AddressNameIndexDataAtom_descriptor = + getDescriptor().getMessageTypes().get(9); + internal_static_AddressNameIndexDataAtom_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_AddressNameIndexDataAtom_descriptor, + new java.lang.String[] { "Name", "NameEn", "Type", "ShiftToIndex", "ShiftToCityIndex", }, + net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.class, + net.osmand.binary.OsmandOdb.AddressNameIndexDataAtom.Builder.class); + internal_static_CityIndex_descriptor = + getDescriptor().getMessageTypes().get(10); + internal_static_CityIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_CityIndex_descriptor, + new java.lang.String[] { "CityType", "Name", "NameEn", "Id", "X", "Y", "ShiftToCityBlockIndex", }, + net.osmand.binary.OsmandOdb.CityIndex.class, + net.osmand.binary.OsmandOdb.CityIndex.Builder.class); + internal_static_CityBlockIndex_descriptor = + getDescriptor().getMessageTypes().get(11); + internal_static_CityBlockIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_CityBlockIndex_descriptor, + new java.lang.String[] { "ShiftToCityIndex", "Buildings", "Streets", }, + net.osmand.binary.OsmandOdb.CityBlockIndex.class, + net.osmand.binary.OsmandOdb.CityBlockIndex.Builder.class); + internal_static_StreetIndex_descriptor = + getDescriptor().getMessageTypes().get(12); + internal_static_StreetIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_StreetIndex_descriptor, + new java.lang.String[] { "Name", "NameEn", "X", "Y", "Id", "Buildings", "Intersections", }, + net.osmand.binary.OsmandOdb.StreetIndex.class, + net.osmand.binary.OsmandOdb.StreetIndex.Builder.class); + internal_static_StreetIntersection_descriptor = + getDescriptor().getMessageTypes().get(13); + internal_static_StreetIntersection_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_StreetIntersection_descriptor, + new java.lang.String[] { "Name", "NameEn", "IntersectedX", "IntersectedY", }, + net.osmand.binary.OsmandOdb.StreetIntersection.class, + net.osmand.binary.OsmandOdb.StreetIntersection.Builder.class); + internal_static_BuildingIndex_descriptor = + getDescriptor().getMessageTypes().get(14); + internal_static_BuildingIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_BuildingIndex_descriptor, + new java.lang.String[] { "Name", "NameEn", "Name2", "NameEn2", "Interpolation", "X", "Y", "X2", "Y2", "Id", "Postcode", }, + net.osmand.binary.OsmandOdb.BuildingIndex.class, + net.osmand.binary.OsmandOdb.BuildingIndex.Builder.class); + internal_static_TransportRoutes_descriptor = + getDescriptor().getMessageTypes().get(15); + internal_static_TransportRoutes_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_TransportRoutes_descriptor, + new java.lang.String[] { "Routes", }, + net.osmand.binary.OsmandOdb.TransportRoutes.class, + net.osmand.binary.OsmandOdb.TransportRoutes.Builder.class); + internal_static_TransportRoute_descriptor = + getDescriptor().getMessageTypes().get(16); + internal_static_TransportRoute_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_TransportRoute_descriptor, + new java.lang.String[] { "Id", "Type", "Operator", "Ref", "Name", "NameEn", "Distance", "DirectStops", "ReverseStops", }, + net.osmand.binary.OsmandOdb.TransportRoute.class, + net.osmand.binary.OsmandOdb.TransportRoute.Builder.class); + internal_static_TransportRouteStop_descriptor = + getDescriptor().getMessageTypes().get(17); + internal_static_TransportRouteStop_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_TransportRouteStop_descriptor, + new java.lang.String[] { "Id", "Dx", "Dy", "Name", "NameEn", }, + net.osmand.binary.OsmandOdb.TransportRouteStop.class, + net.osmand.binary.OsmandOdb.TransportRouteStop.Builder.class); + internal_static_TransportStop_descriptor = + getDescriptor().getMessageTypes().get(18); + internal_static_TransportStop_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_TransportStop_descriptor, + new java.lang.String[] { "Dx", "Dy", "Id", "Name", "NameEn", "Routes", }, + net.osmand.binary.OsmandOdb.TransportStop.class, + net.osmand.binary.OsmandOdb.TransportStop.Builder.class); + internal_static_TransportStopsTree_descriptor = + getDescriptor().getMessageTypes().get(19); + internal_static_TransportStopsTree_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_TransportStopsTree_descriptor, + new java.lang.String[] { "Left", "Right", "Top", "Bottom", "Subtrees", "Leafs", "BaseId", }, + net.osmand.binary.OsmandOdb.TransportStopsTree.class, + net.osmand.binary.OsmandOdb.TransportStopsTree.Builder.class); + internal_static_OsmAndTransportIndex_descriptor = + getDescriptor().getMessageTypes().get(20); + internal_static_OsmAndTransportIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndTransportIndex_descriptor, + new java.lang.String[] { "Name", "Routes", "Stops", "StringTable", }, + net.osmand.binary.OsmandOdb.OsmAndTransportIndex.class, + net.osmand.binary.OsmandOdb.OsmAndTransportIndex.Builder.class); + internal_static_OsmAndPoiIndex_descriptor = + getDescriptor().getMessageTypes().get(21); + internal_static_OsmAndPoiIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiIndex_descriptor, + new java.lang.String[] { "Name", "Boundaries", "CategoriesTable", "NameIndex", "Boxes", "PoiData", }, + net.osmand.binary.OsmandOdb.OsmAndPoiIndex.class, + net.osmand.binary.OsmandOdb.OsmAndPoiIndex.Builder.class); + internal_static_OsmAndPoiNameIndex_descriptor = + getDescriptor().getMessageTypes().get(22); + internal_static_OsmAndPoiNameIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiNameIndex_descriptor, + new java.lang.String[] { "Table", "Data", }, + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.class, + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.Builder.class); + internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_descriptor = + internal_static_OsmAndPoiNameIndex_descriptor.getNestedTypes().get(0); + internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiNameIndex_OsmAndPoiNameIndexData_descriptor, + new java.lang.String[] { "Atoms", }, + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.class, + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndex.OsmAndPoiNameIndexData.Builder.class); + internal_static_OsmAndPoiNameIndexDataAtom_descriptor = + getDescriptor().getMessageTypes().get(23); + internal_static_OsmAndPoiNameIndexDataAtom_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiNameIndexDataAtom_descriptor, + new java.lang.String[] { "Zoom", "X", "Y", "ShiftTo", }, + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.class, + net.osmand.binary.OsmandOdb.OsmAndPoiNameIndexDataAtom.Builder.class); + internal_static_OsmAndCategoryTable_descriptor = + getDescriptor().getMessageTypes().get(24); + internal_static_OsmAndCategoryTable_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndCategoryTable_descriptor, + new java.lang.String[] { "Category", "Subcategories", }, + net.osmand.binary.OsmandOdb.OsmAndCategoryTable.class, + net.osmand.binary.OsmandOdb.OsmAndCategoryTable.Builder.class); + internal_static_OsmAndPoiBox_descriptor = + getDescriptor().getMessageTypes().get(25); + internal_static_OsmAndPoiBox_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiBox_descriptor, + new java.lang.String[] { "Zoom", "Left", "Top", "Categories", "SubBoxes", "ShiftToData", }, + net.osmand.binary.OsmandOdb.OsmAndPoiBox.class, + net.osmand.binary.OsmandOdb.OsmAndPoiBox.Builder.class); + internal_static_OsmAndPoiCategories_descriptor = + getDescriptor().getMessageTypes().get(26); + internal_static_OsmAndPoiCategories_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiCategories_descriptor, + new java.lang.String[] { "Categories", }, + net.osmand.binary.OsmandOdb.OsmAndPoiCategories.class, + net.osmand.binary.OsmandOdb.OsmAndPoiCategories.Builder.class); + internal_static_OsmAndPoiBoxData_descriptor = + getDescriptor().getMessageTypes().get(27); + internal_static_OsmAndPoiBoxData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiBoxData_descriptor, + new java.lang.String[] { "Zoom", "X", "Y", "PoiData", }, + net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.class, + net.osmand.binary.OsmandOdb.OsmAndPoiBoxData.Builder.class); + internal_static_OsmAndPoiBoxDataAtom_descriptor = + getDescriptor().getMessageTypes().get(28); + internal_static_OsmAndPoiBoxDataAtom_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndPoiBoxDataAtom_descriptor, + new java.lang.String[] { "Dx", "Dy", "Categories", "Name", "NameEn", "Id", "OpeningHours", "Site", "Phone", "Note", }, + net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.class, + net.osmand.binary.OsmandOdb.OsmAndPoiBoxDataAtom.Builder.class); + internal_static_IdTable_descriptor = + getDescriptor().getMessageTypes().get(29); + internal_static_IdTable_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_IdTable_descriptor, + new java.lang.String[] { "RouteId", }, + net.osmand.binary.OsmandOdb.IdTable.class, + net.osmand.binary.OsmandOdb.IdTable.Builder.class); + internal_static_RestrictionData_descriptor = + getDescriptor().getMessageTypes().get(30); + internal_static_RestrictionData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_RestrictionData_descriptor, + new java.lang.String[] { "Type", "From", "To", "Via", }, + net.osmand.binary.OsmandOdb.RestrictionData.class, + net.osmand.binary.OsmandOdb.RestrictionData.Builder.class); + internal_static_RouteData_descriptor = + getDescriptor().getMessageTypes().get(31); + internal_static_RouteData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_RouteData_descriptor, + new java.lang.String[] { "Points", "PointTypes", "Types", "RouteId", "StringNames", }, + net.osmand.binary.OsmandOdb.RouteData.class, + net.osmand.binary.OsmandOdb.RouteData.Builder.class); + internal_static_OsmAndRoutingIndex_descriptor = + getDescriptor().getMessageTypes().get(32); + internal_static_OsmAndRoutingIndex_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_descriptor, + new java.lang.String[] { "Name", "Rules", "RootBoxes", "BasemapBoxes", "BorderBox", "BaseBorderBox", "Blocks", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.Builder.class); + internal_static_OsmAndRoutingIndex_RouteEncodingRule_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(0); + internal_static_OsmAndRoutingIndex_RouteEncodingRule_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteEncodingRule_descriptor, + new java.lang.String[] { "Tag", "Value", "Id", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteEncodingRule.Builder.class); + internal_static_OsmAndRoutingIndex_RouteDataBox_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(1); + internal_static_OsmAndRoutingIndex_RouteDataBox_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteDataBox_descriptor, + new java.lang.String[] { "Left", "Right", "Top", "Bottom", "ShiftToData", "Boxes", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBox.Builder.class); + internal_static_OsmAndRoutingIndex_RouteDataBlock_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(2); + internal_static_OsmAndRoutingIndex_RouteDataBlock_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteDataBlock_descriptor, + new java.lang.String[] { "IdTable", "StringTable", "DataObjects", "Restrictions", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteDataBlock.Builder.class); + internal_static_OsmAndRoutingIndex_RouteBorderBox_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(3); + internal_static_OsmAndRoutingIndex_RouteBorderBox_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteBorderBox_descriptor, + new java.lang.String[] { "Boundaries", "TileZoomToSplit", "BorderLines", "Blocks", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderBox.Builder.class); + internal_static_OsmAndRoutingIndex_RouteBorderLine_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(4); + internal_static_OsmAndRoutingIndex_RouteBorderLine_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteBorderLine_descriptor, + new java.lang.String[] { "X", "Y", "Tox", "Toy", "ShiftToPointsBlock", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderLine.Builder.class); + internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(5); + internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteBorderPointsBlock_descriptor, + new java.lang.String[] { "X", "Y", "BaseId", "Points", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPointsBlock.Builder.class); + internal_static_OsmAndRoutingIndex_RouteBorderPoint_descriptor = + internal_static_OsmAndRoutingIndex_descriptor.getNestedTypes().get(6); + internal_static_OsmAndRoutingIndex_RouteBorderPoint_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_OsmAndRoutingIndex_RouteBorderPoint_descriptor, + new java.lang.String[] { "Dx", "Dy", "Direction", "Types", "RoadId", }, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.class, + net.osmand.binary.OsmandOdb.OsmAndRoutingIndex.RouteBorderPoint.Builder.class); + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + } + + public static void internalForceInit() {} + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/OsmAnd-java/src/net/osmand/binary/RouteDataBorderLinePoint.java b/OsmAnd-java/src/net/osmand/binary/RouteDataBorderLinePoint.java new file mode 100644 index 0000000000..f04ca5259b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/RouteDataBorderLinePoint.java @@ -0,0 +1,75 @@ +package net.osmand.binary; + + +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; + +public class RouteDataBorderLinePoint extends RouteDataObject { + // all these arrays supposed to be immutable! + // These feilds accessible from C++ + public int x; + public int y; + public boolean direction; + + // used in context calculation + public float distanceToStartPoint; + public float distanceToEndPoint; + + public RouteDataBorderLinePoint(RouteRegion region) { + super(region); + } + + public float getMaximumSpeed(){ + int sz = types.length; + for (int i = 0; i < sz; i++) { + RouteTypeRule r = region.quickGetEncodingRule(types[i]); + float maxSpeed = r.maxSpeed(); + if (maxSpeed > 0) { + return maxSpeed; + } + } + return 0; + } + + public int getOneway() { + int sz = types.length; + for (int i = 0; i < sz; i++) { + RouteTypeRule r = region.quickGetEncodingRule(types[i]); + if (r.onewayDirection() != 0) { + return r.onewayDirection(); + } else if (r.roundabout()) { + return 1; + } + } + return 0; + } + + public String getRoute() { + int sz = types.length; + for (int i = 0; i < sz; i++) { + RouteTypeRule r = region.quickGetEncodingRule(types[i]); + if ("route".equals(r.getTag())) { + return r.getValue(); + } + } + return null; + } + + public String getHighway() { + String highway = null; + int sz = types.length; + for (int i = 0; i < sz; i++) { + RouteTypeRule r = region.quickGetEncodingRule(types[i]); + highway = r.highwayRoad(); + if (highway != null) { + break; + } + } + return highway; + } + + @Override + public String toString() { + return "Border line " + id; + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/binary/RouteDataObject.java b/OsmAnd-java/src/net/osmand/binary/RouteDataObject.java new file mode 100644 index 0000000000..b5602529e7 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/binary/RouteDataObject.java @@ -0,0 +1,269 @@ +package net.osmand.binary; + + +import gnu.trove.map.hash.TIntObjectHashMap; + +import java.text.MessageFormat; + +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; + +public class RouteDataObject { + /*private */static final int RESTRICTION_SHIFT = 3; + /*private */static final int RESTRICTION_MASK = 7; + + public final RouteRegion region; + // all these arrays supposed to be immutable! + // These fields accessible from C++ + public int[] types; + public int[] pointsX; + public int[] pointsY; + public long[] restrictions; + public int[][] pointTypes; + public long id; + public TIntObjectHashMap names; + public final static float NONE_MAX_SPEED = 40f; + + public RouteDataObject(RouteRegion region) { + this.region = region; + } + + public RouteDataObject(RouteRegion region, int[] nameIds, String[] nameValues) { + this.region = region; + if (nameIds.length > 0) { + names = new TIntObjectHashMap(); + } + for (int i = 0; i < nameIds.length; i++) { + names.put(nameIds[i], nameValues[i]); + } + } + + public RouteDataObject(RouteDataObject copy) { + this.region = copy.region; + this.pointsX = copy.pointsX; + this.pointsY = copy.pointsY; + this.types = copy.types; + this.names = copy.names; + this.restrictions = copy.restrictions; + this.pointTypes = copy.pointTypes; + this.id = copy.id; + } + + public long getId() { + return id; + } + + public String getName(){ + if(names != null ) { + return names.get(region.nameTypeRule); + } + return null; + } + + public String getRef(){ + if(names != null ) { + return names.get(region.refTypeRule); + } + return null; + } + + public String getDestinationName(){ + if(names != null ) { + return names.get(region.destinationTypeRule); + } + return null; + } + + public int getPoint31XTile(int i) { + return pointsX[i]; + } + + public int getPoint31YTile(int i) { + return pointsY[i]; + } + + public int getPointsLength() { + return pointsX.length; + } + + public int getRestrictionLength() { + return restrictions == null ? 0 : restrictions.length; + } + + public int getRestrictionType(int i) { + return (int) (restrictions[i] & RESTRICTION_MASK); + } + + public long getRestrictionId(int i) { + return restrictions[i] >> RESTRICTION_SHIFT; + } + + public void insert(int pos, int x31, int y31) { + int[] opointsX = pointsX; + int[] opointsY = pointsY; + int[][] opointTypes = pointTypes; + pointsX = new int[pointsX.length + 1]; + pointsY = new int[pointsY.length + 1]; + boolean insTypes = this.pointTypes != null && this.pointTypes.length > pos; + if (insTypes) { + pointTypes = new int[opointTypes.length + 1][]; + } + int i = 0; + for (; i < pos; i++) { + pointsX[i] = opointsX[i]; + pointsY[i] = opointsY[i]; + if (insTypes) { + pointTypes[i] = opointTypes[i]; + } + } + pointsX[i] = x31; + pointsY[i] = y31; + if (insTypes) { + pointTypes[i] = null; + } + for (i = i + 1; i < pointsX.length; i++) { + pointsX[i] = opointsX[i - 1]; + pointsY[i] = opointsY[i - 1]; + if (insTypes && i < pointTypes.length) { + pointTypes[i] = opointTypes[i - 1]; + } + } + + } + + public int[] getPointTypes(int ind) { + if (pointTypes == null || ind >= pointTypes.length) { + return null; + } + return pointTypes[ind]; + } + + public int[] getTypes() { + return types; + } + + public float getMaximumSpeed(){ + int sz = types.length; + for (int i = 0; i < sz; i++) { + RouteTypeRule r = region.quickGetEncodingRule(types[i]); + float maxSpeed = r.maxSpeed(); + if (maxSpeed > 0) { + return maxSpeed; + } + } + return 0; + } + + public boolean loop(){ + return pointsX[0] == pointsX[pointsX.length - 1] && pointsY[0] == pointsY[pointsY.length - 1] ; + } + + public boolean roundabout(){ + int sz = types.length; + for(int i=0; i 0) { + return ln; + } + } + return -1; + } + + public double directionRoute(int startPoint, boolean plus) { + // same goes to C++ + // Victor : the problem to put more than 5 meters that BinaryRoutePlanner will treat + // 2 consequent Turn Right as UT and here 2 points will have same turn angle + // So it should be fix in both places + return directionRoute(startPoint, plus, 5); + } + + // Gives route direction of EAST degrees from NORTH ]-PI, PI] + public double directionRoute(int startPoint, boolean plus, float dist) { + int x = getPoint31XTile(startPoint); + int y = getPoint31YTile(startPoint); + int nx = startPoint; + int px = x; + int py = y; + double total = 0; + do { + if (plus) { + nx++; + if (nx >= getPointsLength()) { + break; + } + } else { + nx--; + if (nx < 0) { + break; + } + } + px = getPoint31XTile(nx); + py = getPoint31YTile(nx); + // translate into meters + total += Math.abs(px - x) * 0.011d + Math.abs(py - y) * 0.01863d; + } while (total < dist); + return -Math.atan2( x - px, y - py ); + } + + @Override + public String toString() { + String name = getName(); + String rf = getRef(); + return MessageFormat.format("Road id {0} name {1} ref {2}", getId()+"", name == null ? "" : name, rf == null ? "" : rf); + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/bridge/CoreOsmAnd.java b/OsmAnd-java/src/net/osmand/bridge/CoreOsmAnd.java new file mode 100644 index 0000000000..f0c2c5ec6e --- /dev/null +++ b/OsmAnd-java/src/net/osmand/bridge/CoreOsmAnd.java @@ -0,0 +1,56 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package net.osmand.bridge; + +public class CoreOsmAnd { + public static int get31TileNumberX(double longitude) { + return CoreOsmAndJNI.get31TileNumberX(longitude); + } + + public static int get31TileNumberY(double latitude) { + return CoreOsmAndJNI.get31TileNumberY(latitude); + } + + public static double get31LongitudeX(int x) { + return CoreOsmAndJNI.get31LongitudeX(x); + } + + public static double get31LatitudeY(int y) { + return CoreOsmAndJNI.get31LatitudeY(y); + } + + public static double getTileNumberX(float zoom, double longitude) { + return CoreOsmAndJNI.getTileNumberX(zoom, longitude); + } + + public static double getTileNumberY(float zoom, double latitude) { + return CoreOsmAndJNI.getTileNumberY(zoom, latitude); + } + + public static double checkLatitude(double latitude) { + return CoreOsmAndJNI.checkLatitude(latitude); + } + + public static double checkLongitude(double longitude) { + return CoreOsmAndJNI.checkLongitude(longitude); + } + + public static double getPowZoom(float zoom) { + return CoreOsmAndJNI.getPowZoom(zoom); + } + + public static double getLongitudeFromTile(float zoom, double x) { + return CoreOsmAndJNI.getLongitudeFromTile(zoom, x); + } + + public static double getLatitudeFromTile(float zoom, double y) { + return CoreOsmAndJNI.getLatitudeFromTile(zoom, y); + } + +} diff --git a/OsmAnd-java/src/net/osmand/bridge/CoreOsmAndJNI.java b/OsmAnd-java/src/net/osmand/bridge/CoreOsmAndJNI.java new file mode 100644 index 0000000000..4eb1980bb6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/bridge/CoreOsmAndJNI.java @@ -0,0 +1,37 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package net.osmand.bridge; + +public class CoreOsmAndJNI { + public final static native long new_StringVector__SWIG_0(); + public final static native long new_StringVector__SWIG_1(long jarg1); + public final static native long StringVector_size(long jarg1, StringVector jarg1_); + public final static native long StringVector_capacity(long jarg1, StringVector jarg1_); + public final static native void StringVector_reserve(long jarg1, StringVector jarg1_, long jarg2); + public final static native boolean StringVector_isEmpty(long jarg1, StringVector jarg1_); + public final static native void StringVector_clear(long jarg1, StringVector jarg1_); + public final static native void StringVector_add(long jarg1, StringVector jarg1_, String jarg2); + public final static native String StringVector_get(long jarg1, StringVector jarg1_, int jarg2); + public final static native void StringVector_set(long jarg1, StringVector jarg1_, int jarg2, String jarg3); + public final static native void delete_StringVector(long jarg1); + public final static native int ObfInspector_inspector(long jarg1, StringVector jarg1_); + public final static native long new_ObfInspector(); + public final static native void delete_ObfInspector(long jarg1); + public final static native int get31TileNumberX(double jarg1); + public final static native int get31TileNumberY(double jarg1); + public final static native double get31LongitudeX(int jarg1); + public final static native double get31LatitudeY(int jarg1); + public final static native double getTileNumberX(float jarg1, double jarg2); + public final static native double getTileNumberY(float jarg1, double jarg2); + public final static native double checkLatitude(double jarg1); + public final static native double checkLongitude(double jarg1); + public final static native double getPowZoom(float jarg1); + public final static native double getLongitudeFromTile(float jarg1, double jarg2); + public final static native double getLatitudeFromTile(float jarg1, double jarg2); +} diff --git a/OsmAnd-java/src/net/osmand/bridge/ObfInspector.java b/OsmAnd-java/src/net/osmand/bridge/ObfInspector.java new file mode 100644 index 0000000000..5ee23bd9d5 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/bridge/ObfInspector.java @@ -0,0 +1,46 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package net.osmand.bridge; + +public class ObfInspector { + private long swigCPtr; + protected boolean swigCMemOwn; + + protected ObfInspector(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(ObfInspector obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + CoreOsmAndJNI.delete_ObfInspector(swigCPtr); + } + swigCPtr = 0; + } + } + + public static int inspector(StringVector argv) { + return CoreOsmAndJNI.ObfInspector_inspector(StringVector.getCPtr(argv), argv); + } + + public ObfInspector() { + this(CoreOsmAndJNI.new_ObfInspector(), true); + } + +} diff --git a/OsmAnd-java/src/net/osmand/bridge/StringVector.java b/OsmAnd-java/src/net/osmand/bridge/StringVector.java new file mode 100644 index 0000000000..3fcdb9021c --- /dev/null +++ b/OsmAnd-java/src/net/osmand/bridge/StringVector.java @@ -0,0 +1,84 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package net.osmand.bridge; + +import java.util.AbstractList; +import java.util.List; + +public class StringVector extends AbstractList { + private long swigCPtr; + protected boolean swigCMemOwn; + + protected StringVector(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr(StringVector obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + + protected void finalize() { + delete(); + } + + public synchronized void delete() { + if (swigCPtr != 0) { + if (swigCMemOwn) { + swigCMemOwn = false; + CoreOsmAndJNI.delete_StringVector(swigCPtr); + } + swigCPtr = 0; + } + } + + public StringVector() { + this(CoreOsmAndJNI.new_StringVector__SWIG_0(), true); + } + + public StringVector(long n) { + this(CoreOsmAndJNI.new_StringVector__SWIG_1(n), true); + } + + public int size() { + return (int) CoreOsmAndJNI.StringVector_size(swigCPtr, this); + } + + public long capacity() { + return CoreOsmAndJNI.StringVector_capacity(swigCPtr, this); + } + + public void reserve(long n) { + CoreOsmAndJNI.StringVector_reserve(swigCPtr, this, n); + } + + public boolean isEmpty() { + return CoreOsmAndJNI.StringVector_isEmpty(swigCPtr, this); + } + + public void clear() { + CoreOsmAndJNI.StringVector_clear(swigCPtr, this); + } + + public boolean add(String x) { + CoreOsmAndJNI.StringVector_add(swigCPtr, this, x); + return true; + } + + public String get(int i) { + return CoreOsmAndJNI.StringVector_get(swigCPtr, this, i); + } + + public String set(int i, String val) { + String prev = CoreOsmAndJNI.StringVector_get(swigCPtr, this, i); + CoreOsmAndJNI.StringVector_set(swigCPtr, this, i, val); + return prev; + } + +} diff --git a/OsmAnd-java/src/net/osmand/data/Amenity.java b/OsmAnd-java/src/net/osmand/data/Amenity.java new file mode 100644 index 0000000000..6e7b31643a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/Amenity.java @@ -0,0 +1,72 @@ +package net.osmand.data; + + +public class Amenity extends MapObject { + + private static final long serialVersionUID = 132083949926339552L; + private String subType; + private AmenityType type; + private String openingHours; + private String phone; + private String description; + private String site; + + public Amenity(){ + } + + public AmenityType getType(){ + return type; + } + + public String getSubType(){ + return subType; + } + + public void setType(AmenityType type) { + this.type = type; + } + + public void setSubType(String subType) { + this.subType = subType; + } + + public String getOpeningHours() { + return openingHours; + } + + public void setOpeningHours(String openingHours) { + this.openingHours = openingHours; + } + + + @Override + public String toString() { + return type.toString() + " : " + subType + " "+ getName(); + } + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + +} diff --git a/OsmAnd-java/src/net/osmand/data/AmenityType.java b/OsmAnd-java/src/net/osmand/data/AmenityType.java new file mode 100644 index 0000000000..9e14815d61 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/AmenityType.java @@ -0,0 +1,59 @@ +package net.osmand.data; + +// http://wiki.openstreetmap.org/wiki/Amenity +// POI tags : amenity, leisure, shop, sport, tourism, historic; accessories (internet-access), natural ? +public enum AmenityType { + // Some of those types are subtypes of Amenity tag + SUSTENANCE("amenity"), // restaurant, cafe ... //$NON-NLS-1$ //$NON-NLS-2$ + EDUCATION("amenity"), // school, ... //$NON-NLS-1$ //$NON-NLS-2$ + TRANSPORTATION("amenity"), // car_wash, parking, ... //$NON-NLS-1$ //$NON-NLS-2$ + FINANCE("amenity"), // bank, atm, ... //$NON-NLS-1$ //$NON-NLS-2$ + HEALTHCARE("amenity"), // hospital ... //$NON-NLS-1$ //$NON-NLS-2$ + ENTERTAINMENT("amenity"), // cinema, ... (+! sauna, brothel) //$NON-NLS-1$ //$NON-NLS-2$ + TOURISM("tourism"), // [TAG] tourism hotel, sights, museum .. //$NON-NLS-1$ //$NON-NLS-2$ + HISTORIC("historic"), // [TAG] historic places, monuments (should we unify tourism/historic) //$NON-NLS-1$ //$NON-NLS-2$ + NATURAL("natural"), // [TAG] natural places, monuments (should we unify tourism/historic) //$NON-NLS-1$ //$NON-NLS-2$ + SHOP("shop"), // [TAG] amenity convenience (product), clothes... //$NON-NLS-1$ //$NON-NLS-2$ + LEISURE("leisure"), // [TAG] leisure //$NON-NLS-1$ //$NON-NLS-2$ + SPORT("sport"), // [TAG] sport //$NON-NLS-1$ //$NON-NLS-2$ + BARRIER("barrier"), // [TAG] barrier + traffic_calming //$NON-NLS-1$ //$NON-NLS-2$ + LANDUSE("landuse"), // [TAG] landuse //$NON-NLS-1$ //$NON-NLS-2$ + MAN_MADE("man_made"), // [TAG] man_made and others //$NON-NLS-1$ //$NON-NLS-2$ + OFFICE("office"), // [TAG] office //$NON-NLS-1$ //$NON-NLS-2$ + EMERGENCY("emergency"), // [TAG] emergency //$NON-NLS-1$ //$NON-NLS-2$ + MILITARY("military"), // [TAG] military //$NON-NLS-1$ //$NON-NLS-2$ + ADMINISTRATIVE("administrative"), // [TAG] administrative //$NON-NLS-1$ //$NON-NLS-2$ + GEOCACHE("geocache"), //$NON-NLS-1$ + OSMWIKI("osmwiki"), //$NON-NLS-1$ + USER_DEFINED("user_defined"), //$NON-NLS-1$ + OTHER("amenity"), // grave-yard, police, post-office [+Internet_access] //$NON-NLS-1$ //$NON-NLS-2$ + ; + + private final String defaultTag; + + private AmenityType(String defaultTag) { + this.defaultTag = defaultTag; + } + + public static AmenityType fromString(String s){ + try { + return AmenityType.valueOf(s.toUpperCase()); + } catch (IllegalArgumentException e) { + return AmenityType.OTHER; + } + } + + public String getDefaultTag() { + return defaultTag; + } + + public static String valueToString(AmenityType t){ + return t.toString().toLowerCase(); + } + + public static AmenityType[] getCategories(){ + return AmenityType.values(); + } + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/data/Building.java b/OsmAnd-java/src/net/osmand/data/Building.java new file mode 100644 index 0000000000..1ad8bdbed6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/Building.java @@ -0,0 +1,144 @@ +package net.osmand.data; + + +import net.osmand.util.Algorithms; + +public class Building extends MapObject { + + private String postcode; + private LatLon latLon2; + private BuildingInterpolation interpolationType; + private int interpolationInterval; + private String name2; + + public enum BuildingInterpolation { + ALL(-1), EVEN(-2), ODD(-3), ALPHABETIC(-4); + private final int val; + + BuildingInterpolation(int val) { + this.val = val; + } + public int getValue() { + return val; + } + + public static BuildingInterpolation fromValue(int i){ + for(BuildingInterpolation b : values()) { + if(b.val == i) { + return b; + } + } + return null; + } + } + + public Building(){} + + public String getPostcode() { + return postcode; + } + + public int getInterpolationInterval() { + return interpolationInterval; + } + public void setInterpolationInterval(int interpolationNumber) { + this.interpolationInterval = interpolationNumber; + } + + public BuildingInterpolation getInterpolationType() { + return interpolationType; + } + + public void setInterpolationType(BuildingInterpolation interpolationType) { + this.interpolationType = interpolationType; + } + + public LatLon getLatLon2() { + return latLon2; + } + public void setLatLon2(LatLon latlon2) { + this.latLon2 = latlon2; + } + public String getName2() { + return name2; + } + + public void setName2(String name2) { + this.name2 = name2; + } + + public void setPostcode(String postcode) { + this.postcode = postcode; + } + + @Override + public String getName(boolean en) { + String fname = super.getName(en); + if(interpolationInterval !=0){ + return fname+"-"+name2 +" (+"+interpolationInterval+") "; + } else if(interpolationType != null) { + return fname+"-"+name2 +" ("+interpolationType.toString().toLowerCase()+") "; + } + return name; + } + + + public float interpolation(String hno) { + if(getInterpolationType() != null || getInterpolationInterval() > 0) { + int num = Algorithms.extractFirstIntegerNumber(hno); + int numB = Algorithms.extractFirstIntegerNumber(super.getName()); + int numT = numB; + if (num >= numB) { + if (getName2() != null) { + numT = Algorithms.extractFirstIntegerNumber(getName2()); + if(numT < num) { + return -1; + } + } + if (getInterpolationType() == BuildingInterpolation.EVEN && num % 2 == 1) { + return -1; + } + if (getInterpolationType() == BuildingInterpolation.ODD && num % 2 == 0) { + return -1; + } + if (getInterpolationInterval() != 0 && (num - numB) % getInterpolationInterval() != 0) { + return -1; + } + } else { + return -1; + } + if(numT > numB){ + return ((float)num - numB) / (((float)numT - numB)); + } + return 0; + } + return -1; + } + public boolean belongsToInterpolation(String hno) { + return interpolation(hno) >= 0; + } + + @Override + public String toString() { + if(interpolationInterval !=0){ + return name+"-"+name2 +" (+"+interpolationInterval+") "; + } else if(interpolationType != null) { + return name+"-"+name2 +" ("+interpolationType+") "; + } + return name; + } + + public LatLon getLocation(float interpolation) { + LatLon loc = getLocation(); + LatLon latLon2 = getLatLon2(); + if (latLon2 != null) { + double lat1 = loc.getLatitude(); + double lat2 = latLon2.getLatitude(); + double lon1 = loc.getLongitude(); + double lon2 = latLon2.getLongitude(); + return new LatLon(interpolation * (lat2 - lat1) + lat1, interpolation * (lon2 - lon1) + lon1); + } + return loc; + } + +} diff --git a/OsmAnd-java/src/net/osmand/data/City.java b/OsmAnd-java/src/net/osmand/data/City.java new file mode 100644 index 0000000000..cbadc9c975 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/City.java @@ -0,0 +1,140 @@ +package net.osmand.data; + +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; + +import net.osmand.PlatformUtil; +import net.osmand.util.Algorithms; + +public class City extends MapObject { + public enum CityType { + // that's tricky way to play with that numbers (to avoid including suburbs in city & vice verse) + // district special type and it is not registered as a city + CITY(10000), TOWN(5000), VILLAGE(1300), HAMLET(1000), SUBURB(400), DISTRICT(400); + + private double radius; + + private CityType(double radius) { + this.radius = radius; + } + + public double getRadius() { + return radius; + } + + public static String valueToString(CityType t) { + return t.toString().toLowerCase(); + } + + public static CityType valueFromString(String place) { + if (place == null) { + return null; + } + for (CityType t : CityType.values()) { + if (t.name().equalsIgnoreCase(place)) { + return t; + } + } + return null; + } + } + + private CityType type = null; + // Be attentive ! Working with street names ignoring case + private Map streets = new TreeMap(PlatformUtil.primaryCollator()); + private String isin = null; + private String postcode = null; + + private static long POSTCODE_INTERNAL_ID = -1000; + public static City createPostcode(String postcode){ + return new City(postcode, POSTCODE_INTERNAL_ID--); + } + + public City(CityType type) { + if(type == null) { + throw new NullPointerException(); + } + this.type = type; + } + + public City(String postcode, long id) { + this.type = null; + this.name = this.enName = postcode; + this.id = id; + } + + public String getIsInValue() { + return isin; + } + + public boolean isPostcode(){ + return type == null; + } + + public boolean isEmptyWithStreets() { + return streets.isEmpty(); + } + + + public Street unregisterStreet(String name) { + return streets.remove(name.toLowerCase()); + } + + public void removeAllStreets() { + streets.clear(); + } + + public String getPostcode() { + return postcode; + } + + public void setPostcode(String postcode) { + this.postcode = postcode; + } + + protected Street registerStreet(Street street, boolean en) { + String name = en ? street.getEnName() : street.getName(); + name = name.toLowerCase(); + if (!Algorithms.isEmpty(name)) { + if (!streets.containsKey(name)) { + return streets.put(name, street); + } else { + // try to merge streets + Street prev = streets.get(name); + prev.mergeWith(street); + return prev; + } + } + return null; + } + + public Street registerStreet(Street street) { + return registerStreet(street, false); + } + + public CityType getType() { + return type; + } + + public Collection getStreets() { + return streets.values(); + } + + public Street getStreet(String name) { + return streets.get(name.toLowerCase()); + } + + @Override + public String toString() { + if(isPostcode()) { + return "Postcode : " + getName(); //$NON-NLS-1$ //$NON-NLS-2$ + } + return "City [" + type + "] " + getName(); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public void setIsin(String isin) { + this.isin = isin; + } + +} diff --git a/OsmAnd-java/src/net/osmand/data/DataTileManager.java b/OsmAnd-java/src/net/osmand/data/DataTileManager.java new file mode 100644 index 0000000000..d5196c919f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/DataTileManager.java @@ -0,0 +1,205 @@ +package net.osmand.data; + +import gnu.trove.map.hash.TLongObjectHashMap; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.osmand.util.MapUtils; + +/** + * + * @param - object to store in that manager + */ +public class DataTileManager { + + private final int zoom; + + private TLongObjectHashMap> objects = new TLongObjectHashMap>(); + + public DataTileManager(){ + zoom = 15; + } + + public DataTileManager(int z){ + zoom = z; + } + + public int getZoom() { + return zoom; + } + + + public boolean isEmpty(){ + return getObjectsCount() == 0; + } + + @SuppressWarnings("rawtypes") + public int getObjectsCount(){ + int x = 0; + for(List s : objects.valueCollection()){ + x += s.size(); + } + return x; + } + + private void putObjects(int tx, int ty, List r){ + if(objects.containsKey(evTile(tx, ty))){ + r.addAll(objects.get(evTile(tx, ty))); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public List getAllObjects(){ + List l = new ArrayList(); + for(List s : objects.valueCollection()){ + l.addAll(s); + } + return l; + } + + public List getObjects(double latitudeUp, double longitudeUp, double latitudeDown, double longitudeDown) { + int tileXUp = (int) MapUtils.getTileNumberX(zoom, longitudeUp); + int tileYUp = (int) MapUtils.getTileNumberY(zoom, latitudeUp); + int tileXDown = (int) MapUtils.getTileNumberX(zoom, longitudeDown) + 1; + int tileYDown = (int) MapUtils.getTileNumberY(zoom, latitudeDown) + 1; + List result = new ArrayList(); + for (int i = tileXUp; i <= tileXDown; i++) { + for (int j = tileYUp; j <= tileYDown; j++) { + putObjects(i, j, result); + } + } + return result; + } + + public List getObjects(int leftX31, int topY31, int rightX31, int bottomY31) { + int tileXUp = leftX31 >> (31 - zoom); + int tileYUp = topY31 >> (31 - zoom); + int tileXDown = (rightX31 >> (31 - zoom)) + 1; + int tileYDown = (bottomY31 >> (31 - zoom)) + 1; + List result = new ArrayList(); + for (int i = tileXUp; i <= tileXDown; i++) { + for (int j = tileYUp; j <= tileYDown; j++) { + putObjects(i, j, result); + } + } + return result; + } + + /** + * @depth of the neighbor tile to visit + * returns not exactly sorted list, + * however the first objects are from closer tile than last + */ + public List getClosestObjects(double latitude, double longitude, int defaultStep){ + if(isEmpty()){ + return Collections.emptyList(); + } + int dp = 0; + List l = null; + while (l == null || l.isEmpty()) { + l = getClosestObjects(latitude, longitude, dp, dp + defaultStep); + dp += defaultStep; + } + return l; + } + + public List getClosestObjects(double latitude, double longitude){ + return getClosestObjects(latitude, longitude, 3); + } + + public List getClosestObjects(double latitude, double longitude, int startDepth, int depth){ + int tileX = (int) MapUtils.getTileNumberX(zoom, longitude); + int tileY = (int) MapUtils.getTileNumberY(zoom, latitude); + List result = new ArrayList(); + + if(startDepth <= 0){ + putObjects(tileX, tileY, result); + startDepth = 1; + } + + // that's very difficult way visiting node : + // similar to visit by spiral + // however the simplest way could be to visit row by row & after sort tiles by distance (that's less efficient) + + // go through circle + for (int i = startDepth; i <= depth; i++) { + + // goes + for (int j = 0; j <= i; j++) { + // left & right + int dx = j == 0 ? 0 : -1; + for (; dx < 1 || (j < i && dx == 1); dx += 2) { + // north + putObjects(tileX + dx * j, tileY + i, result); + // east + putObjects(tileX + i, tileY - dx * j, result); + // south + putObjects(tileX - dx * j, tileY - i, result); + // west + putObjects(tileX - i, tileY + dx * j, result); + } + } + } + return result; + } + + private long evTile(int tileX, int tileY){ + long tx = tileX; + long ty = tileY; + return ((tx) << zoom) + ty; + } + + + public long evaluateTile(double latitude, double longitude){ + int tileX = (int) MapUtils.getTileNumberX(zoom, longitude); + int tileY = (int) MapUtils.getTileNumberY(zoom, latitude); + return evTile(tileX, tileY); + } + + public long evaluateTileXY(int x31, int y31){ + return evTile(x31 >> (31 - zoom), y31 >> (31 - zoom)); + } + + public void unregisterObject(double latitude, double longitude, T object){ + long tile = evaluateTile(latitude, longitude); + removeObject(object, tile); + } + + + public void unregisterObjectXY(int x31, int y31, T object){ + long tile = evaluateTileXY(x31, y31); + removeObject(object, tile); + } + + private void removeObject(T object, long tile) { + if(objects.containsKey(tile)){ + objects.get(tile).remove(object); + } + } + + public long registerObjectXY(int x31, int y31, T object){ + return addObject(object, evTile(x31 >> (31 - zoom), y31 >> (31 - zoom))); + } + + public long registerObject(double latitude, double longitude, T object){ + long tile = evaluateTile(latitude, longitude); + return addObject(object, tile); + } + + private long addObject(T object, long tile) { + if(!objects.containsKey(tile)){ + objects.put(tile, new ArrayList()); + } + objects.get(tile).add(object); + return tile; + } + + + public void clear(){ + objects.clear(); + } + + +} diff --git a/OsmAnd-java/src/net/osmand/data/FavouritePoint.java b/OsmAnd-java/src/net/osmand/data/FavouritePoint.java new file mode 100644 index 0000000000..e71b46ed22 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/FavouritePoint.java @@ -0,0 +1,67 @@ +package net.osmand.data; + +import java.io.Serializable; + +public class FavouritePoint implements Serializable { + private static final long serialVersionUID = 729654300829771466L; + private String name; + private String category = ""; + private double latitude; + private double longitude; + private boolean stored = false; + + + public FavouritePoint(){ + } + + public FavouritePoint(double latitude, double longitude, String name, String category) { + this.latitude = latitude; + this.longitude = longitude; + this.category = category; + this.name = name; + } + + public double getLatitude() { + return latitude; + } + + public boolean isStored() { + return stored; + } + public void setStored(boolean stored) { + this.stored = stored; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Favourite " + getName(); //$NON-NLS-1$ + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/data/LatLon.java b/OsmAnd-java/src/net/osmand/data/LatLon.java new file mode 100644 index 0000000000..ff4b718ea3 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/LatLon.java @@ -0,0 +1,54 @@ +package net.osmand.data; + + +public class LatLon { + private final double longitude; + private final double latitude; + + public LatLon(double latitude, double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(latitude); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(longitude); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LatLon other = (LatLon) obj; + if (Double.doubleToLongBits(latitude) != Double.doubleToLongBits(other.latitude)) + return false; + if (Double.doubleToLongBits(longitude) != Double.doubleToLongBits(other.longitude)) + return false; + return true; + } + + @Override + public String toString() { + return "Lat " + ((float)latitude) + " Lon " + ((float)longitude); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/data/MapObject.java b/OsmAnd-java/src/net/osmand/data/MapObject.java new file mode 100644 index 0000000000..291929eb66 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/MapObject.java @@ -0,0 +1,127 @@ +package net.osmand.data; + + +import java.io.Serializable; +import java.util.Comparator; + +import net.osmand.Collator; +import net.osmand.PlatformUtil; + + +public abstract class MapObject implements Comparable, Serializable { + protected String name = null; + protected String enName = null; + protected LatLon location = null; + protected int fileOffset = 0; + protected Long id = null; + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + if(id != null){ + return id; + } + return null; + } + + public String getName(boolean en){ + if(en){ + return getEnName(); + } else { + return getName(); + } + } + + public String getName() { + if (this.name != null) { + return this.name; + } + return ""; //$NON-NLS-1$ + } + + public void setName(String name) { + this.name = name; + } + + public String getEnName() { + if(this.enName != null){ + return this.enName; + } + return ""; //$NON-NLS-1$ + } + + public void setEnName(String enName) { + this.enName = enName; + } + + public LatLon getLocation(){ + return location; + } + + public void setLocation(double latitude, double longitude){ + location = new LatLon(latitude, longitude); + } + + @Override + public int compareTo(MapObject o) { + return PlatformUtil.primaryCollator().compare(getName(), o.getName()); + } + + public int getFileOffset() { + return fileOffset; + } + + public void setFileOffset(int fileOffset) { + this.fileOffset = fileOffset; + } + + @Override + public String toString() { + return getClass().getSimpleName() + " " + name +"("+id+")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.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; + MapObject other = (MapObject) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + public static class MapObjectComparator implements Comparator{ + private final boolean en; + Collator collator = PlatformUtil.primaryCollator(); + public MapObjectComparator(boolean en){ + this.en = en; + } + + @Override + public int compare(MapObject o1, MapObject o2) { + if(en){ + return collator.compare(o1.getEnName(), o2.getEnName()); + } else { + return collator.compare(o1.getName(), o2.getName()); + } + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/data/QuadPoint.java b/OsmAnd-java/src/net/osmand/data/QuadPoint.java new file mode 100644 index 0000000000..7a1814970b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/QuadPoint.java @@ -0,0 +1,24 @@ +package net.osmand.data; + +public class QuadPoint { + public float x; + public float y; + + public QuadPoint() { + } + + public QuadPoint(float x, float y) { + this.x = x; + this.y = y; + } + + public QuadPoint(QuadPoint a) { + this(a.x, a.y); + } + + public void set(float x, float y) { + this.x = x; + this.y = y; + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/data/QuadRect.java b/OsmAnd-java/src/net/osmand/data/QuadRect.java new file mode 100644 index 0000000000..fced8e7c9a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/QuadRect.java @@ -0,0 +1,67 @@ +package net.osmand.data; + +public class QuadRect { + public float left; + public float right; + public float top; + public float bottom; + + public QuadRect(float left, float top, float right, float bottom) { + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; + } + + public QuadRect(QuadRect a) { + this(a.left, a.top, a.right, a.bottom); + } + + public QuadRect() { + } + + public float width() { + return right - left; + } + + public float height() { + return bottom - top; + } + + public boolean contains(float left, float top, float right, float bottom) { + return this.left < this.right && this.top < this.bottom && this.left <= left && this.top <= top && this.right >= right + && this.bottom >= bottom; + } + + public boolean contains(QuadRect box) { + return contains(box.left, box.top, box.right, box.bottom); + } + + public static boolean intersects(QuadRect a, QuadRect b) { + return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom; + } + + public float centerX() { + return (left + right) / 2; + } + + public float centerY() { + return (top + bottom) / 2; + } + + public void offset(float dx, float dy) { + left += dx; + top += dy; + right += dx; + bottom += dy; + + } + + public void inset(float dx, float dy) { + left += dx; + top += dy; + right -= dx; + bottom -= dy; + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/data/QuadTree.java b/OsmAnd-java/src/net/osmand/data/QuadTree.java new file mode 100644 index 0000000000..0ce2127a1f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/QuadTree.java @@ -0,0 +1,102 @@ +package net.osmand.data; + +import java.util.ArrayList; +import java.util.List; + + + + +public class QuadTree { + + private static class Node { + List data = null; + Node[] children = null; + QuadRect bounds; + + @SuppressWarnings("unchecked") + private Node(QuadRect b) { + bounds = new QuadRect(b.left, b.top, b.right, b.bottom); + children = new Node[4]; + } + }; + + private float ratio; + private int maxDepth; + private Node root; + + public QuadTree(QuadRect r, int depth/* =8 */, float ratio /* = 0.55 */) { + this.ratio = ratio; + this.root = new Node(r); + this.maxDepth = depth; + } + + public void insert(T data, QuadRect box) { + int depth = 0; + doInsertData(data, box, root, depth); + } + + public void insert(T data, float x, float y) { + insert(data, new QuadRect(x, y, x, y)); + } + + public void queryInBox(QuadRect box, List result) { + result.clear(); + queryNode(box, result, root); + } + + private void queryNode(QuadRect box, List result, Node node) { + if (node != null) { + if (QuadRect.intersects(box, node.bounds)) { + if (node.data != null) { + result.addAll(node.data); + } + for (int k = 0; k < 4; ++k) { + queryNode(box, result, node.children[k]); + } + } + } + } + + private void doInsertData(T data, QuadRect box, Node n, int depth) { + if (++depth >= maxDepth) { + if (n.data == null) { + n.data = new ArrayList(); + } + n.data.add(data); + } else { + QuadRect[] ext = new QuadRect[4]; + splitBox(n.bounds, ext); + for (int i = 0; i < 4; ++i) { + if (ext[i].contains(box)) { + if (n.children[i] == null) { + n.children[i] = new Node(ext[i]); + } + doInsertData(data, box, n.children[i], depth); + return; + } + } + if (n.data == null) { + n.data = new ArrayList(); + } + n.data.add(data); + } + } + + void splitBox(QuadRect node_extent, QuadRect[] n) { + // coord2d c=node_extent.center(); + + float width = node_extent.width(); + float height = node_extent.height(); + + float lox = node_extent.left; + float loy = node_extent.top; + float hix = node_extent.right; + float hiy = node_extent.bottom; + + n[0] = new QuadRect(lox, loy, lox + width * ratio, loy + height * ratio); + n[1] = new QuadRect(hix - width * ratio, loy, hix, loy + height * ratio); + n[2] = new QuadRect(lox, hiy - height * ratio, lox + width * ratio, hiy); + n[3] = new QuadRect(hix - width * ratio, hiy - height * ratio, hix, hiy); + } + +} diff --git a/OsmAnd-java/src/net/osmand/data/Street.java b/OsmAnd-java/src/net/osmand/data/Street.java new file mode 100644 index 0000000000..e4a2871e8b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/Street.java @@ -0,0 +1,102 @@ +package net.osmand.data; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.osmand.util.Algorithms; + + +public class Street extends MapObject { + + protected List buildings = new ArrayList(); + protected List intersectedStreets = null; + protected final City city; + + public Street(City city) { + this.city = city; + } + + public void addBuilding(Building building){ + buildings.add(building); + } + + public List getIntersectedStreets() { + if(intersectedStreets == null){ + return Collections.emptyList(); + } + return intersectedStreets; + } + + public void addIntersectedStreet(Street s){ + if(intersectedStreets == null) { + intersectedStreets = new ArrayList(); + } + intersectedStreets.add(s); + } + + public void addBuildingCheckById(Building building){ + for(Building b : buildings) { + if(b.getId().longValue() == building.getId().longValue()){ + return; + } + } + buildings.add(building); + } + + public List getBuildings() { + return buildings; + } + + @Override + public void setName(String name) { + if (name.equals(getName())) { + return; + } + if (city != null && city.getStreet(getName()) == this) { + city.unregisterStreet(getName()); + super.setName(name); + Street s = city.registerStreet(this); + } else { + super.setName(name); + } + } + + public String getNameWithoutCityPart(boolean en) { + String nm = getName(en); + int t = nm.lastIndexOf('('); + if(t > 0) { + return nm.substring(0, t); + } + return nm; + + } + + public City getCity() { + return city; + } + + public void sortBuildings(){ + Collections.sort(buildings, new Comparator(){ + @Override + public int compare(Building o1, Building o2) { + String s1 = o1.getName(); + String s2 = o2.getName(); + int i1 = Algorithms.extractFirstIntegerNumber(s1); + int i2 = Algorithms.extractFirstIntegerNumber(s2); + if(i1 == i2) { + String t1 = Algorithms.extractIntegerSuffix(s1); + String t2 = Algorithms.extractIntegerSuffix(s2); + return t1.compareTo(t2); + } + return i1 - i2; + } + }); + } + + public void mergeWith(Street street) { + buildings.addAll(street.getBuildings()); + } + +} diff --git a/OsmAnd-java/src/net/osmand/data/TransportRoute.java b/OsmAnd-java/src/net/osmand/data/TransportRoute.java new file mode 100644 index 0000000000..ca45d1ac38 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/TransportRoute.java @@ -0,0 +1,74 @@ +package net.osmand.data; + +import java.util.ArrayList; +import java.util.List; + +import net.osmand.util.MapUtils; + +public class TransportRoute extends MapObject { + private List forwardStops = new ArrayList(); + private List backwardStops = new ArrayList(); + private String ref; + private String operator; + private String type; + private Integer dist = null; + + public TransportRoute(){ + } + + public List getForwardStops() { + return forwardStops; + } + + public List getBackwardStops() { + return backwardStops; + } + + public String getRef() { + return ref; + } + + public void setRef(String ref) { + this.ref = ref; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getDistance(){ + if(dist == null){ + dist = getAvgBothDistance(); + } + return dist; + } + + public void setDistance(Integer dist) { + this.dist = dist; + } + + public int getAvgBothDistance(){ + int d = 0; + int bSsize = backwardStops.size(); + int fSsize = forwardStops.size(); + for(int i=1; i< bSsize; i++){ + d += MapUtils.getDistance(backwardStops.get(i-1).getLocation(), backwardStops.get(i).getLocation()); + } + for(int i=1; i< fSsize; i++){ + d += MapUtils.getDistance(forwardStops.get(i-1).getLocation(), forwardStops.get(i).getLocation()); + } + return d; + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/data/TransportStop.java b/OsmAnd-java/src/net/osmand/data/TransportStop.java new file mode 100644 index 0000000000..9aa9f3d5fc --- /dev/null +++ b/OsmAnd-java/src/net/osmand/data/TransportStop.java @@ -0,0 +1,17 @@ +package net.osmand.data; + +public class TransportStop extends MapObject { + int[] referencesToRoutes = null; + + public TransportStop(){ + } + + public int[] getReferencesToRoutes() { + return referencesToRoutes; + } + + public void setReferencesToRoutes(int[] referencesToRoutes) { + this.referencesToRoutes = referencesToRoutes; + } + +} diff --git a/OsmAnd-java/src/net/osmand/map/IMapLocationListener.java b/OsmAnd-java/src/net/osmand/map/IMapLocationListener.java new file mode 100644 index 0000000000..7b155eff4b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/IMapLocationListener.java @@ -0,0 +1,5 @@ +package net.osmand.map; + +public interface IMapLocationListener { + void locationChanged(double newLatitude, double newLongitude, Object source); +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/map/ITileSource.java b/OsmAnd-java/src/net/osmand/map/ITileSource.java new file mode 100644 index 0000000000..4e9937ec7f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/ITileSource.java @@ -0,0 +1,24 @@ +package net.osmand.map; + + +public interface ITileSource { + + public int getMaximumZoomSupported(); + + public String getName(); + + public int getTileSize(); + + public String getUrlToLoad(int x, int y, int zoom); + + public int getMinimumZoomSupported(); + + public String getTileFormat(); + + public int getBitDensity(); + + public boolean isEllipticYTile(); + + public boolean couldBeDownloadedFromInternet(); + +} diff --git a/OsmAnd-java/src/net/osmand/map/MapTileDownloader.java b/OsmAnd-java/src/net/osmand/map/MapTileDownloader.java new file mode 100644 index 0000000000..7528c0867d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/MapTileDownloader.java @@ -0,0 +1,230 @@ +package net.osmand.map; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import net.osmand.PlatformUtil; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + + +public class MapTileDownloader { + // Download manager tile settings + public static int TILE_DOWNLOAD_THREADS = 4; + public static int TILE_DOWNLOAD_SECONDS_TO_WORK = 25; + public static final long TIMEOUT_AFTER_EXCEEDING_LIMIT_ERRORS = 20000; + public static final int TILE_DOWNLOAD_MAX_ERRORS_PER_TIMEOUT = 25; + + + private static MapTileDownloader downloader = null; + private static Log log = PlatformUtil.getLog(MapTileDownloader.class); + + public static String USER_AGENT = "OsmAnd~"; + + + private ThreadPoolExecutor threadPoolExecutor; + private List callbacks = new ArrayList(); + + private Set currentlyDownloaded; + + private int currentErrors = 0; + private long timeForErrorCounter = 0; + + + public static MapTileDownloader getInstance(String userAgent){ + if(downloader == null){ + downloader = new MapTileDownloader(TILE_DOWNLOAD_THREADS); + if(userAgent != null) { + MapTileDownloader.USER_AGENT = userAgent; + } + } + return downloader; + } + + /** + * Callback for map downloader + */ + public interface IMapDownloaderCallback { + + /** + * Sometimes null cold be passed as request + * That means that there were a lot of requests but + * once method is called + * (in order to not create a collection of request & reduce calling times) + * @param fileSaved + */ + public void tileDownloaded(DownloadRequest request); + } + + /** + * Download request could subclassed to create own detailed request + */ + public static class DownloadRequest { + public final File fileToSave; + public final int zoom; + public final int xTile; + public final int yTile; + public final String url; + public boolean error; + + public DownloadRequest(String url, File fileToSave, int xTile, int yTile, int zoom) { + this.url = url; + this.fileToSave = fileToSave; + this.xTile = xTile; + this.yTile = yTile; + this.zoom = zoom; + } + + public DownloadRequest(String url, File fileToSave) { + this.url = url; + this.fileToSave = fileToSave; + xTile = -1; + yTile = -1; + zoom = -1; + } + + public void setError(boolean error){ + this.error = error; + } + } + + + public MapTileDownloader(int numberOfThreads){ + threadPoolExecutor = new ThreadPoolExecutor(numberOfThreads, numberOfThreads, TILE_DOWNLOAD_SECONDS_TO_WORK, + TimeUnit.SECONDS, new LinkedBlockingQueue()); + // 1.6 method but very useful to kill non-running threads +// threadPoolExecutor.allowCoreThreadTimeOut(true); + currentlyDownloaded = Collections.synchronizedSet(new HashSet()); + + } + + public void addDownloaderCallback(IMapDownloaderCallback callback){ + callbacks.add(callback); + } + + public void removeDownloaderCallback(IMapDownloaderCallback callback){ + callbacks.remove(callback); + } + + public List getDownloaderCallbacks() { + return callbacks; + } + + public boolean isFileCurrentlyDownloaded(File f){ + return currentlyDownloaded.contains(f); + } + + public boolean isSomethingBeingDownloaded(){ + return !currentlyDownloaded.isEmpty(); + } + + public int getRemainingWorkers(){ + return (int) (threadPoolExecutor.getTaskCount()); + } + + public void refuseAllPreviousRequests(){ + // That's very strange because exception in impl of queue (possibly wrong impl) +// threadPoolExecutor.getQueue().clear(); + while(!threadPoolExecutor.getQueue().isEmpty()){ + threadPoolExecutor.getQueue().poll(); + } + } + + public void requestToDownload(DownloadRequest request){ + long now = System.currentTimeMillis(); + if((int)(now - timeForErrorCounter) > TIMEOUT_AFTER_EXCEEDING_LIMIT_ERRORS ) { + timeForErrorCounter = now; + currentErrors = 0; + } else if(currentErrors > TILE_DOWNLOAD_MAX_ERRORS_PER_TIMEOUT){ + return; + } + if(request.url == null){ + return; + } + + if (!isFileCurrentlyDownloaded(request.fileToSave)) { + threadPoolExecutor.execute(new DownloadMapWorker(request)); + } + } + + + private class DownloadMapWorker implements Runnable, Comparable { + + private DownloadRequest request; + + private DownloadMapWorker(DownloadRequest request){ + this.request = request; + } + + @Override + public void run() { + if (request != null && request.fileToSave != null && request.url != null) { + if(currentlyDownloaded.contains(request.fileToSave)){ + return; + } + + currentlyDownloaded.add(request.fileToSave); + if(log.isDebugEnabled()){ + log.debug("Start downloading tile : " + request.url); //$NON-NLS-1$ + } + long time = System.currentTimeMillis(); + try { + request.fileToSave.getParentFile().mkdirs(); + URL url = new URL(request.url); + URLConnection connection = url.openConnection(); + connection.setRequestProperty("User-Agent", USER_AGENT); //$NON-NLS-1$ + connection.setConnectTimeout(35000); + BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream(), 8 * 1024); + FileOutputStream stream = null; + try { + stream = new FileOutputStream(request.fileToSave); + Algorithms.streamCopy(inputStream, stream); + stream.flush(); + } finally { + Algorithms.closeStream(inputStream); + Algorithms.closeStream(stream); + } + if (log.isDebugEnabled()) { + log.debug("Downloading tile : " + request.url + " successfull " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } catch (UnknownHostException e) { + currentErrors++; + request.setError(true); + log.error("UnknownHostException, cannot download tile " + request.url + " " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (IOException e) { + currentErrors++; + request.setError(true); + log.warn("Cannot download tile : " + request.url, e); //$NON-NLS-1$ + } finally { + currentlyDownloaded.remove(request.fileToSave); + } + if (!request.error) { + for (IMapDownloaderCallback c : new ArrayList(callbacks)) { + c.tileDownloaded(request); + } + } + } + + } + + @Override + public int compareTo(DownloadMapWorker o) { + return 0; //(int) (time - o.time); + } + + } +} diff --git a/OsmAnd-java/src/net/osmand/map/OsmandRegionInfo.java b/OsmAnd-java/src/net/osmand/map/OsmandRegionInfo.java new file mode 100644 index 0000000000..6d5011ae25 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/OsmandRegionInfo.java @@ -0,0 +1,1214 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: DataExtractionOSM/src/osmand_region_info.proto + +package net.osmand.map; + +public final class OsmandRegionInfo { + private OsmandRegionInfo() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + public static final class OsmAndRegionInfo extends + com.google.protobuf.GeneratedMessageLite { + // Use OsmAndRegionInfo.newBuilder() to construct. + private OsmAndRegionInfo() { + initFields(); + } + private OsmAndRegionInfo(boolean noInit) {} + + private static final OsmAndRegionInfo defaultInstance; + public static OsmAndRegionInfo getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndRegionInfo getDefaultInstanceForType() { + return defaultInstance; + } + + // optional .OsmAndRegions regionInfo = 1; + public static final int REGIONINFO_FIELD_NUMBER = 1; + private boolean hasRegionInfo; + private net.osmand.map.OsmandRegionInfo.OsmAndRegions regionInfo_; + public boolean hasRegionInfo() { return hasRegionInfo; } + public net.osmand.map.OsmandRegionInfo.OsmAndRegions getRegionInfo() { return regionInfo_; } + + private void initFields() { + regionInfo_ = net.osmand.map.OsmandRegionInfo.OsmAndRegions.getDefaultInstance(); + } + @Override + public final boolean isInitialized() { + if (hasRegionInfo()) { + if (!getRegionInfo().isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasRegionInfo()) { + output.writeMessage(1, getRegionInfo()); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasRegionInfo()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getRegionInfo()); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo, Builder> { + private net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo result; + + // Construct using net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo(); + return builder; + } + + @Override + protected net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo getDefaultInstanceForType() { + return net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo other) { + if (other == net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo.getDefaultInstance()) return this; + if (other.hasRegionInfo()) { + mergeRegionInfo(other.getRegionInfo()); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 10: { + net.osmand.map.OsmandRegionInfo.OsmAndRegions.Builder subBuilder = net.osmand.map.OsmandRegionInfo.OsmAndRegions.newBuilder(); + if (hasRegionInfo()) { + subBuilder.mergeFrom(getRegionInfo()); + } + input.readMessage(subBuilder, extensionRegistry); + setRegionInfo(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional .OsmAndRegions regionInfo = 1; + public boolean hasRegionInfo() { + return result.hasRegionInfo(); + } + public net.osmand.map.OsmandRegionInfo.OsmAndRegions getRegionInfo() { + return result.getRegionInfo(); + } + public Builder setRegionInfo(net.osmand.map.OsmandRegionInfo.OsmAndRegions value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasRegionInfo = true; + result.regionInfo_ = value; + return this; + } + public Builder setRegionInfo(net.osmand.map.OsmandRegionInfo.OsmAndRegions.Builder builderForValue) { + result.hasRegionInfo = true; + result.regionInfo_ = builderForValue.build(); + return this; + } + public Builder mergeRegionInfo(net.osmand.map.OsmandRegionInfo.OsmAndRegions value) { + if (result.hasRegionInfo() && + result.regionInfo_ != net.osmand.map.OsmandRegionInfo.OsmAndRegions.getDefaultInstance()) { + result.regionInfo_ = + net.osmand.map.OsmandRegionInfo.OsmAndRegions.newBuilder(result.regionInfo_).mergeFrom(value).buildPartial(); + } else { + result.regionInfo_ = value; + } + result.hasRegionInfo = true; + return this; + } + public Builder clearRegionInfo() { + result.hasRegionInfo = false; + result.regionInfo_ = net.osmand.map.OsmandRegionInfo.OsmAndRegions.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRegionInfo) + } + + static { + defaultInstance = new OsmAndRegionInfo(true); + net.osmand.map.OsmandRegionInfo.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRegionInfo) + } + + public static final class OsmAndRegions extends + com.google.protobuf.GeneratedMessageLite { + // Use OsmAndRegions.newBuilder() to construct. + private OsmAndRegions() { + initFields(); + } + private OsmAndRegions(boolean noInit) {} + + private static final OsmAndRegions defaultInstance; + public static OsmAndRegions getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndRegions getDefaultInstanceForType() { + return defaultInstance; + } + + // repeated .OsmAndRegion regions = 3; + public static final int REGIONS_FIELD_NUMBER = 3; + private java.util.List regions_ = + java.util.Collections.emptyList(); + public java.util.List getRegionsList() { + return regions_; + } + public int getRegionsCount() { return regions_.size(); } + public net.osmand.map.OsmandRegionInfo.OsmAndRegion getRegions(int index) { + return regions_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + for (net.osmand.map.OsmandRegionInfo.OsmAndRegion element : getRegionsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + for (net.osmand.map.OsmandRegionInfo.OsmAndRegion element : getRegionsList()) { + output.writeMessage(3, element); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + for (net.osmand.map.OsmandRegionInfo.OsmAndRegion element : getRegionsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, element); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegions parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.map.OsmandRegionInfo.OsmAndRegions prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.map.OsmandRegionInfo.OsmAndRegions, Builder> { + private net.osmand.map.OsmandRegionInfo.OsmAndRegions result; + + // Construct using net.osmand.map.OsmandRegionInfo.OsmAndRegions.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.map.OsmandRegionInfo.OsmAndRegions(); + return builder; + } + + @Override + protected net.osmand.map.OsmandRegionInfo.OsmAndRegions internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.map.OsmandRegionInfo.OsmAndRegions(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegions getDefaultInstanceForType() { + return net.osmand.map.OsmandRegionInfo.OsmAndRegions.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegions build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.map.OsmandRegionInfo.OsmAndRegions buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegions buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.regions_ != java.util.Collections.EMPTY_LIST) { + result.regions_ = + java.util.Collections.unmodifiableList(result.regions_); + } + net.osmand.map.OsmandRegionInfo.OsmAndRegions returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.map.OsmandRegionInfo.OsmAndRegions other) { + if (other == net.osmand.map.OsmandRegionInfo.OsmAndRegions.getDefaultInstance()) return this; + if (!other.regions_.isEmpty()) { + if (result.regions_.isEmpty()) { + result.regions_ = new java.util.ArrayList(); + } + result.regions_.addAll(other.regions_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 26: { + net.osmand.map.OsmandRegionInfo.OsmAndRegion.Builder subBuilder = net.osmand.map.OsmandRegionInfo.OsmAndRegion.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addRegions(subBuilder.buildPartial()); + break; + } + } + } + } + + + // repeated .OsmAndRegion regions = 3; + public java.util.List getRegionsList() { + return java.util.Collections.unmodifiableList(result.regions_); + } + public int getRegionsCount() { + return result.getRegionsCount(); + } + public net.osmand.map.OsmandRegionInfo.OsmAndRegion getRegions(int index) { + return result.getRegions(index); + } + public Builder setRegions(int index, net.osmand.map.OsmandRegionInfo.OsmAndRegion value) { + if (value == null) { + throw new NullPointerException(); + } + result.regions_.set(index, value); + return this; + } + public Builder setRegions(int index, net.osmand.map.OsmandRegionInfo.OsmAndRegion.Builder builderForValue) { + result.regions_.set(index, builderForValue.build()); + return this; + } + public Builder addRegions(net.osmand.map.OsmandRegionInfo.OsmAndRegion value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.regions_.isEmpty()) { + result.regions_ = new java.util.ArrayList(); + } + result.regions_.add(value); + return this; + } + public Builder addRegions(net.osmand.map.OsmandRegionInfo.OsmAndRegion.Builder builderForValue) { + if (result.regions_.isEmpty()) { + result.regions_ = new java.util.ArrayList(); + } + result.regions_.add(builderForValue.build()); + return this; + } + public Builder addAllRegions( + java.lang.Iterable values) { + if (result.regions_.isEmpty()) { + result.regions_ = new java.util.ArrayList(); + } + super.addAll(values, result.regions_); + return this; + } + public Builder clearRegions() { + result.regions_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRegions) + } + + static { + defaultInstance = new OsmAndRegions(true); + net.osmand.map.OsmandRegionInfo.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRegions) + } + + public static final class OsmAndRegion extends + com.google.protobuf.GeneratedMessageLite { + // Use OsmAndRegion.newBuilder() to construct. + private OsmAndRegion() { + initFields(); + } + private OsmAndRegion(boolean noInit) {} + + private static final OsmAndRegion defaultInstance; + public static OsmAndRegion getDefaultInstance() { + return defaultInstance; + } + + @Override + public OsmAndRegion getDefaultInstanceForType() { + return defaultInstance; + } + + // optional string continentName = 1; + public static final int CONTINENTNAME_FIELD_NUMBER = 1; + private boolean hasContinentName; + private java.lang.String continentName_ = ""; + public boolean hasContinentName() { return hasContinentName; } + public java.lang.String getContinentName() { return continentName_; } + + // required string name = 2; + public static final int NAME_FIELD_NUMBER = 2; + private boolean hasName; + private java.lang.String name_ = ""; + public boolean hasName() { return hasName; } + public java.lang.String getName() { return name_; } + + // repeated int32 degX = 4 [packed = true]; + public static final int DEGX_FIELD_NUMBER = 4; + private java.util.List degX_ = + java.util.Collections.emptyList(); + public java.util.List getDegXList() { + return degX_; + } + public int getDegXCount() { return degX_.size(); } + public int getDegX(int index) { + return degX_.get(index); + } + private int degXMemoizedSerializedSize = -1; + + // repeated int32 degY = 5 [packed = true]; + public static final int DEGY_FIELD_NUMBER = 5; + private java.util.List degY_ = + java.util.Collections.emptyList(); + public java.util.List getDegYList() { + return degY_; + } + public int getDegYCount() { return degY_.size(); } + public int getDegY(int index) { + return degY_.get(index); + } + private int degYMemoizedSerializedSize = -1; + + // repeated .OsmAndRegion subregions = 8; + public static final int SUBREGIONS_FIELD_NUMBER = 8; + private java.util.List subregions_ = + java.util.Collections.emptyList(); + public java.util.List getSubregionsList() { + return subregions_; + } + public int getSubregionsCount() { return subregions_.size(); } + public net.osmand.map.OsmandRegionInfo.OsmAndRegion getSubregions(int index) { + return subregions_.get(index); + } + + private void initFields() { + } + @Override + public final boolean isInitialized() { + if (!hasName) return false; + for (net.osmand.map.OsmandRegionInfo.OsmAndRegion element : getSubregionsList()) { + if (!element.isInitialized()) return false; + } + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasContinentName()) { + output.writeString(1, getContinentName()); + } + if (hasName()) { + output.writeString(2, getName()); + } + if (getDegXList().size() > 0) { + output.writeRawVarint32(34); + output.writeRawVarint32(degXMemoizedSerializedSize); + } + for (int element : getDegXList()) { + output.writeInt32NoTag(element); + } + if (getDegYList().size() > 0) { + output.writeRawVarint32(42); + output.writeRawVarint32(degYMemoizedSerializedSize); + } + for (int element : getDegYList()) { + output.writeInt32NoTag(element); + } + for (net.osmand.map.OsmandRegionInfo.OsmAndRegion element : getSubregionsList()) { + output.writeMessage(8, element); + } + } + + private int memoizedSerializedSize = -1; + @Override + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasContinentName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getContinentName()); + } + if (hasName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getName()); + } + { + int dataSize = 0; + for (int element : getDegXList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(element); + } + size += dataSize; + if (!getDegXList().isEmpty()) { + size += 1; + size += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(dataSize); + } + degXMemoizedSerializedSize = dataSize; + } + { + int dataSize = 0; + for (int element : getDegYList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(element); + } + size += dataSize; + if (!getDegYList().isEmpty()) { + size += 1; + size += com.google.protobuf.CodedOutputStream + .computeInt32SizeNoTag(dataSize); + } + degYMemoizedSerializedSize = dataSize; + } + for (net.osmand.map.OsmandRegionInfo.OsmAndRegion element : getSubregionsList()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(8, element); + } + memoizedSerializedSize = size; + return size; + } + + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static net.osmand.map.OsmandRegionInfo.OsmAndRegion parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + @Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(net.osmand.map.OsmandRegionInfo.OsmAndRegion prototype) { + return newBuilder().mergeFrom(prototype); + } + @Override + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + net.osmand.map.OsmandRegionInfo.OsmAndRegion, Builder> { + private net.osmand.map.OsmandRegionInfo.OsmAndRegion result; + + // Construct using net.osmand.map.OsmandRegionInfo.OsmAndRegion.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new net.osmand.map.OsmandRegionInfo.OsmAndRegion(); + return builder; + } + + @Override + protected net.osmand.map.OsmandRegionInfo.OsmAndRegion internalGetResult() { + return result; + } + + @Override + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new net.osmand.map.OsmandRegionInfo.OsmAndRegion(); + return this; + } + + @Override + public Builder clone() { + return create().mergeFrom(result); + } + + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegion getDefaultInstanceForType() { + return net.osmand.map.OsmandRegionInfo.OsmAndRegion.getDefaultInstance(); + } + + @Override + public boolean isInitialized() { + return result.isInitialized(); + } + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegion build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private net.osmand.map.OsmandRegionInfo.OsmAndRegion buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + @Override + public net.osmand.map.OsmandRegionInfo.OsmAndRegion buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.degX_ != java.util.Collections.EMPTY_LIST) { + result.degX_ = + java.util.Collections.unmodifiableList(result.degX_); + } + if (result.degY_ != java.util.Collections.EMPTY_LIST) { + result.degY_ = + java.util.Collections.unmodifiableList(result.degY_); + } + if (result.subregions_ != java.util.Collections.EMPTY_LIST) { + result.subregions_ = + java.util.Collections.unmodifiableList(result.subregions_); + } + net.osmand.map.OsmandRegionInfo.OsmAndRegion returnMe = result; + result = null; + return returnMe; + } + + @Override + public Builder mergeFrom(net.osmand.map.OsmandRegionInfo.OsmAndRegion other) { + if (other == net.osmand.map.OsmandRegionInfo.OsmAndRegion.getDefaultInstance()) return this; + if (other.hasContinentName()) { + setContinentName(other.getContinentName()); + } + if (other.hasName()) { + setName(other.getName()); + } + if (!other.degX_.isEmpty()) { + if (result.degX_.isEmpty()) { + result.degX_ = new java.util.ArrayList(); + } + result.degX_.addAll(other.degX_); + } + if (!other.degY_.isEmpty()) { + if (result.degY_.isEmpty()) { + result.degY_ = new java.util.ArrayList(); + } + result.degY_.addAll(other.degY_); + } + if (!other.subregions_.isEmpty()) { + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + result.subregions_.addAll(other.subregions_); + } + return this; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 10: { + setContinentName(input.readString()); + break; + } + case 18: { + setName(input.readString()); + break; + } + case 32: { + addDegX(input.readInt32()); + break; + } + case 34: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addDegX(input.readInt32()); + } + input.popLimit(limit); + break; + } + case 40: { + addDegY(input.readInt32()); + break; + } + case 42: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + while (input.getBytesUntilLimit() > 0) { + addDegY(input.readInt32()); + } + input.popLimit(limit); + break; + } + case 66: { + net.osmand.map.OsmandRegionInfo.OsmAndRegion.Builder subBuilder = net.osmand.map.OsmandRegionInfo.OsmAndRegion.newBuilder(); + input.readMessage(subBuilder, extensionRegistry); + addSubregions(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional string continentName = 1; + public boolean hasContinentName() { + return result.hasContinentName(); + } + public java.lang.String getContinentName() { + return result.getContinentName(); + } + public Builder setContinentName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasContinentName = true; + result.continentName_ = value; + return this; + } + public Builder clearContinentName() { + result.hasContinentName = false; + result.continentName_ = getDefaultInstance().getContinentName(); + return this; + } + + // required string name = 2; + public boolean hasName() { + return result.hasName(); + } + public java.lang.String getName() { + return result.getName(); + } + public Builder setName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasName = true; + result.name_ = value; + return this; + } + public Builder clearName() { + result.hasName = false; + result.name_ = getDefaultInstance().getName(); + return this; + } + + // repeated int32 degX = 4 [packed = true]; + public java.util.List getDegXList() { + return java.util.Collections.unmodifiableList(result.degX_); + } + public int getDegXCount() { + return result.getDegXCount(); + } + public int getDegX(int index) { + return result.getDegX(index); + } + public Builder setDegX(int index, int value) { + result.degX_.set(index, value); + return this; + } + public Builder addDegX(int value) { + if (result.degX_.isEmpty()) { + result.degX_ = new java.util.ArrayList(); + } + result.degX_.add(value); + return this; + } + public Builder addAllDegX( + java.lang.Iterable values) { + if (result.degX_.isEmpty()) { + result.degX_ = new java.util.ArrayList(); + } + super.addAll(values, result.degX_); + return this; + } + public Builder clearDegX() { + result.degX_ = java.util.Collections.emptyList(); + return this; + } + + // repeated int32 degY = 5 [packed = true]; + public java.util.List getDegYList() { + return java.util.Collections.unmodifiableList(result.degY_); + } + public int getDegYCount() { + return result.getDegYCount(); + } + public int getDegY(int index) { + return result.getDegY(index); + } + public Builder setDegY(int index, int value) { + result.degY_.set(index, value); + return this; + } + public Builder addDegY(int value) { + if (result.degY_.isEmpty()) { + result.degY_ = new java.util.ArrayList(); + } + result.degY_.add(value); + return this; + } + public Builder addAllDegY( + java.lang.Iterable values) { + if (result.degY_.isEmpty()) { + result.degY_ = new java.util.ArrayList(); + } + super.addAll(values, result.degY_); + return this; + } + public Builder clearDegY() { + result.degY_ = java.util.Collections.emptyList(); + return this; + } + + // repeated .OsmAndRegion subregions = 8; + public java.util.List getSubregionsList() { + return java.util.Collections.unmodifiableList(result.subregions_); + } + public int getSubregionsCount() { + return result.getSubregionsCount(); + } + public net.osmand.map.OsmandRegionInfo.OsmAndRegion getSubregions(int index) { + return result.getSubregions(index); + } + public Builder setSubregions(int index, net.osmand.map.OsmandRegionInfo.OsmAndRegion value) { + if (value == null) { + throw new NullPointerException(); + } + result.subregions_.set(index, value); + return this; + } + public Builder setSubregions(int index, net.osmand.map.OsmandRegionInfo.OsmAndRegion.Builder builderForValue) { + result.subregions_.set(index, builderForValue.build()); + return this; + } + public Builder addSubregions(net.osmand.map.OsmandRegionInfo.OsmAndRegion value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + result.subregions_.add(value); + return this; + } + public Builder addSubregions(net.osmand.map.OsmandRegionInfo.OsmAndRegion.Builder builderForValue) { + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + result.subregions_.add(builderForValue.build()); + return this; + } + public Builder addAllSubregions( + java.lang.Iterable values) { + if (result.subregions_.isEmpty()) { + result.subregions_ = new java.util.ArrayList(); + } + super.addAll(values, result.subregions_); + return this; + } + public Builder clearSubregions() { + result.subregions_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:OsmAndRegion) + } + + static { + defaultInstance = new OsmAndRegion(true); + net.osmand.map.OsmandRegionInfo.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:OsmAndRegion) + } + + + static { + } + + public static void internalForceInit() {} + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/OsmAnd-java/src/net/osmand/map/RegionCountry.java b/OsmAnd-java/src/net/osmand/map/RegionCountry.java new file mode 100644 index 0000000000..a8db5be963 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/RegionCountry.java @@ -0,0 +1,110 @@ +package net.osmand.map; + +import gnu.trove.list.array.TIntArrayList; + +import java.util.ArrayList; +import java.util.List; + +import net.osmand.map.OsmandRegionInfo.OsmAndRegion; +import net.osmand.util.Algorithms; + +public class RegionCountry { + public String continentName; + public TIntArrayList tiles = new TIntArrayList(); + public int left, right, top, bottom; + public String name; + public RegionCountry parent; + + private List regions = new ArrayList(); + + public void add(int xdeg, int ydeg) { + if (tiles.size() == 0) { + left = right = xdeg; + top = bottom = ydeg; + } + left = Math.min(xdeg, left); + right = Math.max(xdeg, right); + bottom = Math.min(ydeg, bottom); + top = Math.max(ydeg, top); + tiles.add(xdeg); + tiles.add(ydeg); + } + + public int getTileSize() { + return tiles.size()/2; + } + + public int getLon(int i) { + return tiles.get(i*2); + } + + public int getLat(int i) { + return tiles.get(i*2 + 1); + } + + public void addSubregion(RegionCountry c) { + c.parent = this; + regions.add(c); + } + + public List getSubRegions() { + return regions; + } + + /*public TLongHashSet calculateTileSet(TLongHashSet t, int z) { + for (int j = 0; j < tiles.size(); j++) { + int kx = (int) MapUtils.getTileNumberX(z, getLon(j)); + int ex = (int) MapUtils.getTileNumberX(z, getLon(j) + 0.9999f); + int ky = (int) MapUtils.getTileNumberY(z, getLat(j)); + int ey = (int) MapUtils.getTileNumberY(z, getLat(j) - 0.9999f); + for (int x = kx; x <= ex; x++) { + for (int y = ky; y <= ey; y++) { + long v = (((long) y) << 31) + x; + t.add(v); + } + } + } + return t; + }*/ + + public static RegionCountry construct(OsmAndRegion reg) { + RegionCountry rc = new RegionCountry(); + if (reg.hasContinentName()) { + rc.continentName = reg.getContinentName(); + } + rc.name = reg.getName(); + int px = 0; + int py = 0; + for (int i = 0; i < reg.getDegXCount(); i++) { + px = reg.getDegX(i) + px; + py = reg.getDegY(i) + py; + rc.add(px, py); + } + for (int i = 0; i < reg.getSubregionsCount(); i++) { + rc.addSubregion(construct(reg.getSubregions(i))); + } + return rc; + } + + public OsmAndRegion convert() { + OsmAndRegion.Builder reg = OsmAndRegion.newBuilder(); + // System.out.println(r.name + " " + r.tiles.size() + " ?= " + r.calculateTileSet(new TLongHashSet(), 8).size()); + int px = 0; + int py = 0; + for (int i = 0; i < this.getTileSize(); i++) { + reg.addDegX(this.getLon(i) - px); + reg.addDegY(this.getLat(i) - py); + px = this.getLon(i); + py = this.getLat(i); + } + String n = Algorithms.capitalizeFirstLetterAndLowercase(this.name.replace('_', ' ')); + reg.setName(n); + if(this.continentName != null) { + reg.setContinentName(Algorithms.capitalizeFirstLetterAndLowercase(this.continentName)); + } + for (RegionCountry c : this.regions) { + reg.addSubregions(c.convert()); + } + return reg.build(); + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/map/RegionRegistry.java b/OsmAnd-java/src/net/osmand/map/RegionRegistry.java new file mode 100644 index 0000000000..b13be09cb4 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/RegionRegistry.java @@ -0,0 +1,44 @@ +package net.osmand.map; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import net.osmand.PlatformUtil; +import net.osmand.map.OsmandRegionInfo.OsmAndRegionInfo; + +import org.apache.commons.logging.Log; + +public class RegionRegistry { + public static final String fileName = "countries.reginfo"; + private static final Log log = PlatformUtil.getLog(RegionRegistry.class); + private static RegionRegistry r = null; + + private List countries = new ArrayList(); + + public static RegionRegistry getRegionRegistry(){ + if(r == null) { + try { + long t = -System.currentTimeMillis(); + r = new RegionRegistry(); + InputStream in = RegionRegistry.class.getResourceAsStream(RegionRegistry.fileName); + OsmAndRegionInfo regInfo = OsmAndRegionInfo.newBuilder().mergeFrom(in).build(); + for(int j = 0; j < regInfo.getRegionInfo().getRegionsCount(); j++) { + r.countries.add(RegionCountry.construct(regInfo.getRegionInfo().getRegions(j))); + } + t += System.currentTimeMillis(); + log.info("Initialize regions from file" + t + " ms"); + } catch (IOException e) { + log.error("IO exception reading regions", e); + } + } + return r; + } + + + public List getCountries() { + return countries; + } + +} diff --git a/OsmAnd-java/src/net/osmand/map/TileSourceManager.java b/OsmAnd-java/src/net/osmand/map/TileSourceManager.java new file mode 100644 index 0000000000..d374e00d8f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/map/TileSourceManager.java @@ -0,0 +1,482 @@ +package net.osmand.map; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.net.URLConnection; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.osmand.PlatformUtil; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import bsh.Interpreter; + + +public class TileSourceManager { + private static final Log log = PlatformUtil.getLog(TileSourceManager.class); + private static final String RULE_BEANSHELL = "beanshell"; + public static final String RULE_YANDEX_TRAFFIC = "yandex_traffic"; + private static final String RULE_WMS = "wms_tile"; + + public static class TileSourceTemplate implements ITileSource { + private int maxZoom; + private int minZoom; + private String name; + protected int tileSize; + protected String urlToLoad; + protected String ext; + private int avgSize; + private int bitDensity; + private boolean ellipticYTile; + private String rule; + private boolean isRuleAcceptable = true; + + public TileSourceTemplate(String name, String urlToLoad, String ext, int maxZoom, int minZoom, int tileSize, int bitDensity, + int avgSize) { + this.maxZoom = maxZoom; + this.minZoom = minZoom; + this.name = name; + this.tileSize = tileSize; + this.urlToLoad = urlToLoad; + this.ext = ext; + this.avgSize = avgSize; + this.bitDensity = bitDensity; + } + + public void setEllipticYTile(boolean ellipticYTile) { + this.ellipticYTile = ellipticYTile; + } + + @Override + public boolean isEllipticYTile() { + return ellipticYTile; + } + + @Override + public int getBitDensity() { + return bitDensity; + } + + public int getAverageSize() { + return avgSize; + } + + @Override + public int getMaximumZoomSupported() { + return maxZoom; + } + + @Override + public int getMinimumZoomSupported() { + return minZoom; + } + + @Override + public String getName() { + return name; + } + + @Override + public int getTileSize() { + return tileSize; + } + + @Override + public String getTileFormat() { + return ext; + } + + public boolean isRuleAcceptable() { + return isRuleAcceptable; + } + + public void setRuleAcceptable(boolean isRuleAcceptable) { + this.isRuleAcceptable = isRuleAcceptable; + } + + @Override + public String getUrlToLoad(int x, int y, int zoom) { + // use int to string not format numbers! (non-nls) + if (urlToLoad == null) { + return null; + } + return MessageFormat.format(urlToLoad, zoom + "", x + "", y + ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + public String getUrlTemplate() { + return urlToLoad; + } + + @Override + public boolean couldBeDownloadedFromInternet() { + return urlToLoad != null; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.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; + TileSourceTemplate other = (TileSourceTemplate) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + public void setRule(String rule) { + this.rule = rule; + } + + public String getRule() { + return rule; + } + } + + private static Map readMetaInfoFile(File dir) { + Map keyValueMap = new LinkedHashMap(); + try { + + File metainfo = new File(dir, ".metainfo"); //$NON-NLS-1$ + if (metainfo.exists()) { + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(metainfo), "UTF-8")); //$NON-NLS-1$ + String line; + String key = null; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.startsWith("[")) { + key = line.substring(1, line.length() - 1).toLowerCase(); + } else if (key != null && line.length() > 0) { + keyValueMap.put(key, line); + key = null; + } + } + reader.close(); + } + } catch (IOException e) { + log.error("Error reading metainfo file " + dir.getAbsolutePath(), e); + } + return keyValueMap; + } + + private static int parseInt(Map attributes, String value, int def){ + String val = attributes.get(value); + if(val == null){ + return def; + } + try { + return Integer.parseInt(val); + } catch (NumberFormatException e) { + return def; + } + } + + public static void createMetaInfoFile(File dir, TileSourceTemplate tm, boolean override) throws IOException { + File metainfo = new File(dir, ".metainfo"); //$NON-NLS-1$ + Map properties = new LinkedHashMap(); + if (tm instanceof BeanShellTileSourceTemplate) { + properties.put("rule", RULE_BEANSHELL); + } + if (tm.getUrlTemplate() == null) { + return; + } + properties.put("url_template", tm.getUrlTemplate()); + + properties.put("ext", tm.getTileFormat()); + properties.put("min_zoom", tm.getMinimumZoomSupported() + ""); + properties.put("max_zoom", tm.getMaximumZoomSupported() + ""); + properties.put("tile_size", tm.getTileSize() + ""); + properties.put("img_density", tm.getBitDensity() + ""); + properties.put("avg_img_size", tm.getAverageSize() + ""); + + if (tm.isEllipticYTile()) { + properties.put("ellipsoid", tm.isEllipticYTile() + ""); + } + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(metainfo))); + for (String key : properties.keySet()) { + writer.write("[" + key + "]\n" + properties.get(key) + "\n"); + } + writer.close(); + } + + public static boolean isTileSourceMetaInfoExist(File dir){ + return new File(dir, ".metainfo").exists() || new File(dir, "url").exists(); + } + + /** + * @param dir + * @return doesn't return null + */ + public static TileSourceTemplate createTileSourceTemplate(File dir) { + // read metainfo file + Map metaInfo = readMetaInfoFile(dir); + boolean ruleAcceptable = true; + if(!metaInfo.isEmpty()){ + metaInfo.put("name", dir.getName()); + TileSourceTemplate template = createTileSourceTemplate(metaInfo); + if(template != null){ + return template; + } + ruleAcceptable = false; + } + + // try to find url + String ext = findOneTile(dir); + ext = ext == null ? ".jpg" : ext; + String url = null; + File readUrl = new File(dir, "url"); //$NON-NLS-1$ + try { + if (readUrl.exists()) { + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(readUrl), "UTF-8")); //$NON-NLS-1$ + url = reader.readLine(); + // + url = url.replaceAll("\\{\\$z\\}", "{0}"); //$NON-NLS-1$ //$NON-NLS-2$ + url = url.replaceAll("\\{\\$x\\}", "{1}"); //$NON-NLS-1$//$NON-NLS-2$ + url = url.replaceAll("\\{\\$y\\}", "{2}"); //$NON-NLS-1$ //$NON-NLS-2$ + reader.close(); + } + } catch (IOException e) { + log.debug("Error reading url " + dir.getName(), e); //$NON-NLS-1$ + } + + TileSourceTemplate template = new TileSourceManager.TileSourceTemplate(dir.getName(), url, + ext, 18, 1, 256, 16, 20000); //$NON-NLS-1$ + template.setRuleAcceptable(ruleAcceptable); + return template; + } + + private static String findOneTile(File dir) { + if (dir.isDirectory()) { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + String ext = findOneTile(file); + if (ext != null) { + return ext; + } + } else { + String fileName = file.getName(); + if (fileName.endsWith(".tile")) { + String substring = fileName.substring(0, fileName.length() - ".tile".length()); + int extInt = substring.lastIndexOf("."); + if (extInt != -1) { + return substring.substring(extInt, substring.length()); + } + } + } + } + } + return null; + } + + public static java.util.List getKnownSourceTemplates() { + java.util.List list = new ArrayList(); + list.add(getMapnikSource()); + list.add(getCycleMapSource()); + return list; + + } + + public static TileSourceTemplate getMapnikSource(){ + return new TileSourceTemplate("Mapnik", "http://mapnik.osmand.net/{0}/{1}/{2}.png", ".png", 18, 1, 256, 8, 18000); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + } + + public static TileSourceTemplate getCycleMapSource(){ + return new TileSourceTemplate("CycleMap", "http://b.tile.opencyclemap.org/cycle/{0}/{1}/{2}.png", ".png", 16, 1, 256, 32, 18000); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + } + + + public static List downloadTileSourceTemplates(String versionAsUrl) { + final List templates = new ArrayList(); + try { + URLConnection connection = new URL("http://download.osmand.net//tile_sources.php?" + versionAsUrl).openConnection(); + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + parser.setInput(connection.getInputStream(), "UTF-8"); + int tok; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + String name = parser.getName(); + if (name.equals("tile_source")) { + Map attrs = new LinkedHashMap(); + for(int i=0; i< parser.getAttributeCount(); i++) { + attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i)); + } + TileSourceTemplate template = createTileSourceTemplate(attrs); + if (template != null) { + templates.add(template); + } + } + } + } + } catch (IOException e) { + log.error("Exception while downloading tile sources", e); + return null; + } catch (XmlPullParserException e) { + log.error("Exception while downloading tile sources", e); + return null; + } + return templates; + } + + private static TileSourceTemplate createTileSourceTemplate(Map attrs) { + TileSourceTemplate template = null; + String rule = attrs.get("rule"); + if(rule == null){ + template = createSimpleTileSourceTemplate(attrs, false); + } else if(RULE_BEANSHELL.equalsIgnoreCase(rule)){ + template = createBeanshellTileSourceTemplate(attrs); + } else if (RULE_WMS.equalsIgnoreCase(rule)) { + template = createWmsTileSourceTemplate(attrs); + } else if (RULE_YANDEX_TRAFFIC.equalsIgnoreCase(rule)) { + template = createSimpleTileSourceTemplate(attrs, true); + } else { + return null; + } + if(template != null){ + template.setRule(rule); + } + return template; + } + + + private static TileSourceTemplate createWmsTileSourceTemplate(Map attributes) { + String name = attributes.get("name"); + String layer = attributes.get("layer"); + String urlTemplate = attributes.get("url_template"); + + if (name == null || urlTemplate == null || layer == null) { + return null; + } + int maxZoom = parseInt(attributes, "max_zoom", 18); + int minZoom = parseInt(attributes, "min_zoom", 5); + int tileSize = parseInt(attributes, "tile_size", 256); + String ext = attributes.get("ext") == null ? ".jpg" : attributes.get("ext"); + int bitDensity = parseInt(attributes, "img_density", 16); + int avgTileSize = parseInt(attributes, "avg_img_size", 18000); + urlTemplate = " http://whoots.mapwarper.net/tms/{0}/{1}/{2}/"+layer+"/"+urlTemplate; + TileSourceTemplate templ = new TileSourceTemplate(name, urlTemplate, ext, maxZoom, minZoom, tileSize, bitDensity, avgTileSize); + return templ; + } + + + + private static TileSourceTemplate createSimpleTileSourceTemplate(Map attributes, boolean ignoreTemplate) { + String name = attributes.get("name"); + String urlTemplate = attributes.get("url_template"); + if (name == null || (urlTemplate == null && !ignoreTemplate)) { + return null; + } + if(urlTemplate != null){ + urlTemplate.replace("${x}", "{1}").replace("${y}", "{2}").replace("${z}", "{0}"); + } + int maxZoom = parseInt(attributes, "max_zoom", 18); + int minZoom = parseInt(attributes, "min_zoom", 5); + int tileSize = parseInt(attributes, "tile_size", 256); + String ext = attributes.get("ext") == null ? ".jpg" : attributes.get("ext"); + int bitDensity = parseInt(attributes, "img_density", 16); + int avgTileSize = parseInt(attributes, "avg_img_size", 18000); + boolean ellipsoid = false; + if (Boolean.parseBoolean(attributes.get("ellipsoid"))) { + ellipsoid = true; + } + TileSourceTemplate templ = new TileSourceTemplate(name, urlTemplate, ext, maxZoom, minZoom, tileSize, bitDensity, avgTileSize); + templ.setEllipticYTile(ellipsoid); + return templ; + } + + private static TileSourceTemplate createBeanshellTileSourceTemplate(Map attributes) { + String name = attributes.get("name"); + String urlTemplate = attributes.get("url_template"); + if (name == null || urlTemplate == null) { + return null; + } + int maxZoom = parseInt(attributes, "max_zoom", 18); + int minZoom = parseInt(attributes, "min_zoom", 5); + int tileSize = parseInt(attributes, "tile_size", 256); + String ext = attributes.get("ext") == null ? ".jpg" : attributes.get("ext"); + int bitDensity = parseInt(attributes, "img_density", 16); + int avgTileSize = parseInt(attributes, "avg_img_size", 18000); + boolean ellipsoid = false; + if (Boolean.parseBoolean(attributes.get("ellipsoid"))) { + ellipsoid = true; + } + TileSourceTemplate templ; + templ = new BeanShellTileSourceTemplate(name, urlTemplate, ext, maxZoom, minZoom, tileSize, bitDensity, avgTileSize); + templ.setEllipticYTile(ellipsoid); + return templ; + } + + public static class BeanShellTileSourceTemplate extends TileSourceTemplate { + + Interpreter bshInterpreter; + + public BeanShellTileSourceTemplate(String name, String urlToLoad, String ext, + int maxZoom, int minZoom, int tileSize, int bitDensity, int avgSize) { + super(name, urlToLoad, ext, maxZoom, minZoom, tileSize, bitDensity, avgSize); + bshInterpreter = new Interpreter(); + try { + bshInterpreter.eval(urlToLoad); + bshInterpreter.getClassManager().setClassLoader(new ClassLoader() { + @Override + public URL getResource(String resName) { + return null; + } + + @Override + public InputStream getResourceAsStream(String resName) { + return null; + } + + @Override + public Class loadClass(String className) throws ClassNotFoundException { + throw new ClassNotFoundException("Error requesting " + className); + } + }); + } catch (bsh.EvalError e) { + log.error("Error executing the map init script " + urlToLoad, e); + } + } + + @Override + public String getUrlToLoad(int x, int y, int zoom) { + try { + return (String) bshInterpreter.eval("getTileUrl("+zoom+","+x+","+y+");"); + } catch (bsh.EvalError e) { + log.error(e.getMessage(), e); + return null; + } + } + + } + + +} diff --git a/OsmAnd-java/src/net/osmand/map/countries.reginfo b/OsmAnd-java/src/net/osmand/map/countries.reginfo new file mode 100644 index 0000000000..01be8ebf4e Binary files /dev/null and b/OsmAnd-java/src/net/osmand/map/countries.reginfo differ diff --git a/OsmAnd-java/src/net/osmand/osm/MapRenderingTypes.java b/OsmAnd-java/src/net/osmand/osm/MapRenderingTypes.java new file mode 100644 index 0000000000..00ae6b1b91 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/MapRenderingTypes.java @@ -0,0 +1,319 @@ +package net.osmand.osm; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +import net.osmand.PlatformUtil; +import net.osmand.data.AmenityType; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +/** + * reference : http://wiki.openstreetmap.org/wiki/Map_Features + */ +public class MapRenderingTypes { + + private static final Log log = PlatformUtil.getLog(MapRenderingTypes.class); + + public final static byte RESTRICTION_NO_RIGHT_TURN = 1; + public final static byte RESTRICTION_NO_LEFT_TURN = 2; + public final static byte RESTRICTION_NO_U_TURN = 3; + public final static byte RESTRICTION_NO_STRAIGHT_ON = 4; + public final static byte RESTRICTION_ONLY_RIGHT_TURN = 5; + public final static byte RESTRICTION_ONLY_LEFT_TURN = 6; + public final static byte RESTRICTION_ONLY_STRAIGHT_ON = 7; + + private static char TAG_DELIMETER = '/'; //$NON-NLS-1$ + + private String resourceName = null; + private Map> amenityTypeNameToTagVal = null; + private Map amenityNameToType = null; + private Map amenityTypes = null; + + public MapRenderingTypes(String fileName){ + this.resourceName = fileName; + } + + private static MapRenderingTypes DEFAULT_INSTANCE = null; + + public static MapRenderingTypes getDefault() { + if(DEFAULT_INSTANCE == null){ + DEFAULT_INSTANCE = new MapRenderingTypes(null); + } + return DEFAULT_INSTANCE; + } + + private Map getAmenityEncodingRuleTypes(){ + checkIfInitNeeded(); + return amenityTypes; + } + + protected void checkIfInitNeeded() { + if(amenityTypes == null) { + amenityTypes = new LinkedHashMap(); + init(); + } + } + + public Map> getAmenityTypeNameToTagVal() { + if (amenityTypeNameToTagVal == null) { + Map types = getAmenityEncodingRuleTypes(); + amenityTypeNameToTagVal = new LinkedHashMap>(); + for(AmenityRuleType type : types.values()){ + if(type.poiCategory != null && type.targetTagValue == null) { + if(!amenityTypeNameToTagVal.containsKey(type.poiCategory)) { + amenityTypeNameToTagVal.put(type.poiCategory, new TreeMap()); + } + String name = type.value; + if (name != null) { + if (type.poiPrefix != null) { + name = type.poiPrefix + name; + amenityTypeNameToTagVal.get(type.poiCategory).put(name, type.tag + " " + type.value); + } else { + amenityTypeNameToTagVal.get(type.poiCategory).put(name, type.tag); + } + } + } + } + } + return amenityTypeNameToTagVal; + } + + + public Map getAmenityNameToType(){ + if(amenityNameToType == null){ + amenityNameToType = new LinkedHashMap(); + Map> map = getAmenityTypeNameToTagVal(); + Iterator>> iter = map.entrySet().iterator(); + while(iter.hasNext()){ + Entry> e = iter.next(); + for(String t : e.getValue().keySet()){ + if (t != null) { + if (amenityNameToType.containsKey(t)) { + System.err.println("Conflict " + t + " " + amenityNameToType.get(t) + " <> " + e.getKey()); + } + amenityNameToType.put(t, e.getKey()); + } + } + } + } + return amenityNameToType; + } + + public Collection getAmenitySubCategories(AmenityType t){ + Map> amenityTypeNameToTagVal = getAmenityTypeNameToTagVal(); + if(!amenityTypeNameToTagVal.containsKey(t)){ + return Collections.emptyList(); + } + return amenityTypeNameToTagVal.get(t).keySet(); + } + + + public String getAmenitySubtype(String tag, String val){ + String prefix = getAmenitySubtypePrefix(tag, val); + if(prefix != null){ + return prefix + val; + } + return val; + } + + public String getAmenitySubtypePrefix(String tag, String val){ + Map rules = getAmenityEncodingRuleTypes(); + AmenityRuleType rt = rules.get(constructRuleKey(tag, val)); + if(rt != null && rt.poiPrefix != null) { + return rt.poiPrefix; + } + rt = rules.get(constructRuleKey(tag, null)); + if(rt != null && rt.poiPrefix != null) { + return rt.poiPrefix; + } + return null; + } + + public AmenityType getAmenityType(String tag, String val){ + return getAmenityType(tag, val, false); + } + + public AmenityType getAmenityType(String tag, String val, boolean relation){ + // register amenity types + Map rules = getAmenityEncodingRuleTypes(); + AmenityRuleType rt = rules.get(constructRuleKey(tag, val)); + if(rt != null && rt.poiSpecified) { + if(relation && !rt.relation) { + return null; + } + return rt.poiCategory; + } + rt = rules.get(constructRuleKey(tag, null)); + if(rt != null && rt.poiSpecified) { + if(relation && !rt.relation) { + return null; + } + return rt.poiCategory; + } + return null; + } + + + protected void init(){ + InputStream is; + try { + if(resourceName == null){ + is = MapRenderingTypes.class.getResourceAsStream("rendering_types.xml"); //$NON-NLS-1$ + } else { + is = new FileInputStream(resourceName); + } + long time = System.currentTimeMillis(); + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + int tok; + parser.setInput(is, "UTF-8"); + String poiParentCategory = null; + String poiParentPrefix = null; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + String name = parser.getName(); + if (name.equals("category")) { //$NON-NLS-1$ + poiParentCategory = parser.getAttributeValue("","poi_category"); + poiParentPrefix = parser.getAttributeValue("","poi_prefix"); + parseCategoryFromXml(parser, poiParentCategory, poiParentPrefix); + } else if (name.equals("type")) { + parseTypeFromXML(parser, poiParentCategory, poiParentPrefix); + } else if (name.equals("routing_type")) { + parseRouteTagFromXML(parser); + } + } + } + log.info("Time to init " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ + is.close(); + } catch (IOException e) { + log.error("Unexpected error", e); //$NON-NLS-1$ + e.printStackTrace(); + throw new RuntimeException(e); + } catch (RuntimeException e) { + log.error("Unexpected error", e); //$NON-NLS-1$ + e.printStackTrace(); + throw e; + } catch (XmlPullParserException e) { + log.error("Unexpected error", e); //$NON-NLS-1$ + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + protected void parseRouteTagFromXML(XmlPullParser parser) { + } + + protected void parseTypeFromXML(XmlPullParser parser, String poiParentCategory, String poiParentPrefix) { + AmenityRuleType rtype = new AmenityRuleType(); + rtype.tag = parser.getAttributeValue("", "tag"); //$NON-NLS-1$ + rtype.value = parser.getAttributeValue("", "value"); //$NON-NLS-1$ + if (rtype.value != null && rtype.value.length() == 0) { //$NON-NLS-1$ + rtype.value = null; + } + if (poiParentCategory != null) { + rtype.poiCategory = AmenityType.valueOf(poiParentCategory.toUpperCase()); + rtype.poiSpecified = true; + } + if (poiParentPrefix != null) { + rtype.poiPrefix = poiParentPrefix; + } + + String poiCategory = parser.getAttributeValue("", "poi_category"); + if (poiCategory != null) { + rtype.poiSpecified = true; + if (poiCategory.length() == 0) { + rtype.poiCategory = null; + } else { + rtype.poiCategory = AmenityType.valueOf(poiCategory.toUpperCase()); + } + } + String poiPrefix = parser.getAttributeValue("", "poi_prefix"); + if (poiPrefix != null) { + rtype.poiPrefix = poiPrefix; + } + rtype.relation = Boolean.parseBoolean(parser.getAttributeValue("", "relation")); + if (rtype.poiSpecified) { + registerAmenityType(rtype.tag, rtype.value, rtype); + String targetTag = parser.getAttributeValue("", "target_tag"); + String targetValue = parser.getAttributeValue("", "target_value"); + if (targetTag != null || targetValue != null) { + if (targetTag == null) { + targetTag = rtype.tag; + } + if (targetValue == null) { + targetValue = rtype.value; + } + rtype.targetTagValue = amenityTypes.get(constructRuleKey(targetTag, targetValue)); + } + } + } + + private AmenityRuleType registerAmenityType(String tag, String val, AmenityRuleType rt) { + String keyVal = constructRuleKey(tag, val); + if (amenityTypes.containsKey(keyVal)) { + throw new RuntimeException("Duplicate " + keyVal); + } else { + amenityTypes.put(keyVal, rt); + return rt; + } + } + + protected void parseCategoryFromXml(XmlPullParser parser, String poiParentCategory, String poiParentPrefix) { + String tag = parser.getAttributeValue("","poi_tag"); + if (tag != null) { + AmenityRuleType rtype = new AmenityRuleType(); + rtype.poiCategory = AmenityType.valueOf(poiParentCategory.toUpperCase()); + rtype.poiSpecified = true; + rtype.relation = Boolean.parseBoolean(parser.getAttributeValue("", "relation")); + rtype.poiPrefix = poiParentPrefix; + rtype.tag = tag; + registerAmenityType(tag, null, rtype); + } + } + + protected static String constructRuleKey(String tag, String val) { + if(val == null || val.length() == 0){ + return tag; + } + return tag + TAG_DELIMETER + val; + } + + protected static String getTagKey(String tagValue) { + int i = tagValue.indexOf(TAG_DELIMETER); + if(i >= 0){ + return tagValue.substring(0, i); + } + return tagValue; + } + + protected static String getValueKey(String tagValue) { + int i = tagValue.indexOf(TAG_DELIMETER); + if(i >= 0){ + return tagValue.substring(i + 1); + } + return null; + } + + + private static class AmenityRuleType { + protected String tag; + protected String value; + protected String poiPrefix; + protected boolean relation; + protected AmenityType poiCategory; + protected boolean poiSpecified; + protected AmenityRuleType targetTagValue; + } + +} + diff --git a/OsmAnd-java/src/net/osmand/osm/edit/Entity.java b/OsmAnd-java/src/net/osmand/osm/edit/Entity.java new file mode 100644 index 0000000000..adeae27dd6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/Entity.java @@ -0,0 +1,238 @@ +package net.osmand.osm.edit; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import net.osmand.data.LatLon; +import net.osmand.osm.edit.OSMSettings.OSMTagKey; + + +public abstract class Entity { + public enum EntityType { + NODE, + WAY, + RELATION, + WAY_BOUNDARY; + + public static EntityType valueOf(Entity e){ + if(e instanceof Node){ + return NODE; + } else if(e instanceof Way){ + return WAY; + } else if(e instanceof Relation){ + return RELATION; + } + return null; + } + } + + public static class EntityId { + private final EntityType type; + private final Long id; + + + public EntityId(EntityType type, Long id){ + this.type = type; + this.id = id; + } + + public static EntityId valueOf(Entity e){ + return new EntityId(EntityType.valueOf(e), e.getId()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public String toString() { + return type + " " + id; //$NON-NLS-1$ + } + + public EntityType getType() { + return type; + } + + public Long getId() { + return id; + } + + public String getOsmUrl() { + final String browseUrl = "http://www.openstreetmap.org/browse/"; + if (type == EntityType.NODE) + return browseUrl + "node/" + id; + if (type == EntityType.WAY) + return browseUrl + "way/" + id; + return null; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + EntityId other = (EntityId) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + } + + // lazy initializing + private Map tags = null; + private final long id; + private boolean dataLoaded; + + public Entity(long id) { + this.id = id; + } + + public Entity(Entity copy, long id) { + this.id = id; + for (String t : copy.getTagKeySet()) { + putTag(t, copy.getTag(t)); + } + this.dataLoaded = copy.dataLoaded; + } + + public long getId() { + return id; + } + + public String removeTag(String key){ + return tags.remove(key); + } + + public void removeTags(String[] keys){ + if (tags != null){ + for (String key : keys){ + tags.remove(key); + } + } + } + + public String putTag(String key, String value){ + if(tags == null){ + tags = new LinkedHashMap(); + } + return tags.put(key, value); + } + + public String getTag(OSMTagKey key){ + return getTag(key.getValue()); + } + + public String getTag(String key){ + if(tags == null){ + return null; + } + return tags.get(key); + } + + public Map getTags() { + if(tags == null){ + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(tags); + } + + + public Collection getTagKeySet(){ + if(tags == null){ + return Collections.emptyList(); + } + return tags.keySet(); + } + + public abstract void initializeLinks(Map entities); + + + /** + * @return middle point for entity + */ + public abstract LatLon getLatLon(); + + + public boolean isVirtual(){ + return id < 0; + } + + public String getOsmUrl() { + return EntityId.valueOf(this).getOsmUrl(); + } + + @Override + public String toString() { + return EntityId.valueOf(this).toString(); + } + @Override + public int hashCode() { + if (id < 0) { + return System.identityHashCode(this); + } + return (int) id; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Entity other = (Entity) obj; + if (id != other.id) + return false; + // virtual are not equal + if(id < 0){ + return false; + } + return true; + } + + public Set getIsInNames() { + String values = getTag(OSMTagKey.IS_IN); + if (values == null) { + return Collections.emptySet(); + } + if (values.indexOf(';') != -1) { + String[] splitted = values.split(";"); + Set set = new HashSet(splitted.length); + for (int i = 0; i < splitted.length; i++) { + set.add(splitted[i].trim()); + } + return set; + } + return Collections.singleton(values.trim()); + } + + public void entityDataLoaded() { + this.dataLoaded = true; + } + + public boolean isDataLoaded() { + return dataLoaded; + } +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/EntityInfo.java b/OsmAnd-java/src/net/osmand/osm/edit/EntityInfo.java new file mode 100644 index 0000000000..4e22156d13 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/EntityInfo.java @@ -0,0 +1,67 @@ +package net.osmand.osm.edit; + +/** + * Additional entity info + */ +public class EntityInfo { + String timestamp; + String uid; + String user; + String visible; + String version; + String changeset; + String action; + + + public EntityInfo() { + } + + public EntityInfo(String version) { + this.version = version; + } + + + public String getAction() { + return action; + } + public void setAction(String action) { + this.action = action; + } + public String getTimestamp() { + return timestamp; + } + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + public String getUid() { + return uid; + } + public void setUid(String uid) { + this.uid = uid; + } + public String getUser() { + return user; + } + public void setUser(String user) { + this.user = user; + } + public String getVisible() { + return visible; + } + public void setVisible(String visible) { + this.visible = visible; + } + public String getVersion() { + return version; + } + public void setVersion(String version) { + this.version = version; + } + public String getChangeset() { + return changeset; + } + public void setChangeset(String changeset) { + this.changeset = changeset; + } + +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/EntityParser.java b/OsmAnd-java/src/net/osmand/osm/edit/EntityParser.java new file mode 100644 index 0000000000..3ad3152395 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/EntityParser.java @@ -0,0 +1,180 @@ +package net.osmand.osm.edit; + +import java.util.Collection; +import java.util.List; + +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.data.Building; +import net.osmand.data.City; +import net.osmand.data.City.CityType; +import net.osmand.data.LatLon; +import net.osmand.data.MapObject; +import net.osmand.data.TransportStop; +import net.osmand.osm.MapRenderingTypes; +import net.osmand.osm.edit.OSMSettings.OSMTagKey; +import net.osmand.util.Algorithms; + +public class EntityParser { + + private static void parseMapObject(MapObject mo, Entity e) { + mo.setId(e.getId()); + if(mo instanceof Amenity) { + mo.setId((e.getId() << 1) + ((e instanceof Node) ? 0 : 1)); + } + if (mo.getName().length() == 0) { + mo.setName(e.getTag(OSMTagKey.NAME)); + } + if (mo.getEnName().length() == 0) { + mo.setEnName(e.getTag(OSMTagKey.NAME_EN)); + if (mo.getName().length() == 0) { + mo.setName(mo.getEnName()); + } + } + if (mo.getLocation() == null) { + LatLon l = OsmMapUtils.getCenter(e); + if (l != null) { + mo.setLocation(l.getLatitude(), l.getLongitude()); + } + } + if (mo.getName().length() == 0) { + setNameFromOperator(mo, e); + } + if (mo.getName().length() == 0) { + setNameFromRef(mo, e); + } + } + + private static void setNameFromRef(MapObject mo, Entity e) { + String ref = e.getTag(OSMTagKey.REF); + if(ref != null){ + mo.setName(ref); + } + } + + private static void setNameFromOperator(MapObject mo,Entity e) { + String op = e.getTag(OSMTagKey.OPERATOR); + if (op == null) + return; + String ref = e.getTag(OSMTagKey.REF); + if (ref != null) + op += " [" + ref + "]"; + mo.setName(op); + } + + public static void parseAmenity(Amenity am, Entity entity) { + parseMapObject(am, entity); + + } + + public static Amenity parseAmenity(Entity entity, AmenityType type, String subtype) { + Amenity am = new Amenity(); + parseAmenity(am, entity); + am.setType(type); + am.setSubType(subtype); + am.setOpeningHours(entity.getTag(OSMTagKey.OPENING_HOURS)); + am.setPhone(entity.getTag(OSMTagKey.PHONE)); + if (am.getPhone() == null) { + am.setPhone(entity.getTag(OSMTagKey.CONTACT_PHONE)); + } + String siteUrl = entity.getTag(OSMTagKey.WIKIPEDIA); + if (siteUrl != null) { + if (!siteUrl.startsWith("http://")) { //$NON-NLS-1$ + int i = siteUrl.indexOf(':'); + if (i == -1) { + siteUrl = "http://en.wikipedia.org/wiki/" + siteUrl; //$NON-NLS-1$ + } else { + siteUrl = "http://" + siteUrl.substring(0, i) + ".wikipedia.org/wiki/" + siteUrl.substring(i + 1); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } else { + siteUrl = entity.getTag(OSMTagKey.WEBSITE); + if (siteUrl == null) { + siteUrl = entity.getTag(OSMTagKey.URL); + if (siteUrl == null) { + siteUrl = entity.getTag(OSMTagKey.CONTACT_WEBSITE); + } + } + if (siteUrl != null && !siteUrl.startsWith("http://")) { + siteUrl = "http://" + siteUrl; + } + } + am.setSite(siteUrl); + am.setDescription(entity.getTag(OSMTagKey.DESCRIPTION)); + return am; + } + + public static List parseAmenities(MapRenderingTypes renderingTypes, + Entity entity, List amenitiesList){ + // it could be collection of amenities + boolean relation = entity instanceof Relation; + Collection keySet = entity.getTagKeySet(); + if (!keySet.isEmpty()) { + for (String t : keySet) { + AmenityType type = renderingTypes.getAmenityType(t, entity.getTag(t), relation); + if (type != null) { + String subtype = renderingTypes.getAmenitySubtype(t, entity.getTag(t)); + Amenity a = parseAmenity(entity, type, subtype); + if(checkAmenitiesToAdd(a, amenitiesList) && !"no".equals(subtype)){ + amenitiesList.add(a); + } + } + } + } + return amenitiesList; + } + + private static boolean checkAmenitiesToAdd(Amenity a, List amenitiesList){ + // check amenity for duplication + for(Amenity b : amenitiesList){ + if(b.getType() == a.getType() && Algorithms.objectEquals(a.getSubType(), b.getSubType())){ + return false; + } + } + return true; + + } + + public static Building parseBuilding(Entity e){ + Building b = new Building(); + parseMapObject(b, e); + // try to extract postcode + String p = e.getTag(OSMTagKey.ADDR_POSTCODE); + if(p == null) { + p = e.getTag(OSMTagKey.POSTAL_CODE); + } + b.setPostcode(p); + return b; + } + + public static City parseCity(Node el) { + return parseCity(el, CityType.valueFromString(el.getTag(OSMTagKey.PLACE))); + } + + public static City parseCity(Entity el, CityType t) { + if(t == null) { + return null; + } + City c = new City(t); + parseMapObject(c, el); + String isin = el.getTag(OSMTagKey.IS_IN); + isin = isin != null ? isin.toLowerCase() : null; + c.setIsin(isin); + return c; + } + + + public static OsmTransportRoute parserRoute(Relation r, String ref){ + OsmTransportRoute rt = new OsmTransportRoute(); + parseMapObject(rt, r); + rt.setRef(ref); + return rt; + } + + public static TransportStop parseTransportStop(Entity e){ + TransportStop st = new TransportStop(); + parseMapObject(st, e); + return st; + } + +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/Node.java b/OsmAnd-java/src/net/osmand/osm/edit/Node.java new file mode 100644 index 0000000000..a0a8c36e93 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/Node.java @@ -0,0 +1,55 @@ +package net.osmand.osm.edit; + +import java.io.Serializable; +import java.util.Map; + +import net.osmand.data.LatLon; + +public class Node extends Entity implements Serializable { + + private static final long serialVersionUID = -2981499160640211082L; + private double latitude; + private double longitude; + // currently not used +// private boolean visible = true; + + public Node(double latitude, double longitude, long id){ + super(id); + this.latitude = latitude; + this.longitude = longitude; + } + + public Node(Node n, long newId) { + super(n, newId); + this.latitude = n.latitude; + this.longitude = n.longitude; + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + @Override + public LatLon getLatLon() { + return new LatLon(latitude, longitude); + } + + @Override + public void initializeLinks(Map entities) { + // nothing to initialize + + } + +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/OSMSettings.java b/OsmAnd-java/src/net/osmand/osm/edit/OSMSettings.java new file mode 100644 index 0000000000..f30a196dd6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/OSMSettings.java @@ -0,0 +1,109 @@ +package net.osmand.osm.edit; + +public class OSMSettings { + + public enum OSMTagKey { + NAME("name"), //$NON-NLS-1$ + NAME_EN("name:en"), //$NON-NLS-1$ + + // ways + HIGHWAY("highway"), //$NON-NLS-1$ + BUILDING("building"), //$NON-NLS-1$ + BOUNDARY("boundary"), //$NON-NLS-1$ + POSTAL_CODE("postal_code"), //$NON-NLS-1$ + RAILWAY("railway"), //$NON-NLS-1$ + ONEWAY("oneway"), //$NON-NLS-1$ + LAYER("layer"), //$NON-NLS-1$ + BRIDGE("bridge"), //$NON-NLS-1$ + TUNNEL("tunnel"), //$NON-NLS-1$ + TOLL("toll"), //$NON-NLS-1$ + JUNCTION("junction"), //$NON-NLS-1$ + + + // transport + ROUTE("route"), //$NON-NLS-1$ + ROUTE_MASTER("route_master"), //$NON-NLS-1$ + OPERATOR("operator"), //$NON-NLS-1$ + REF("ref"), //$NON-NLS-1$ + RCN_REF("rcn_ref"), //$NON-NLS-1$ + RWN_REF("rwn_ref"), //$NON-NLS-1$ + + // address + PLACE("place"), //$NON-NLS-1$ + ADDR_HOUSE_NUMBER("addr:housenumber"), //$NON-NLS-1$ + ADDR_STREET("addr:street"), //$NON-NLS-1$ + ADDR_STREET2("addr:street2"), //$NON-NLS-1$ + ADDR_CITY("addr:city"), //$NON-NLS-1$ + ADDR_POSTCODE("addr:postcode"), //$NON-NLS-1$ + ADDR_INTERPOLATION("addr:interpolation"), //$NON-NLS-1$ + ADDRESS_TYPE("address:type"), //$NON-NLS-1$ + ADDRESS_HOUSE("address:house"), //$NON-NLS-1$ + TYPE("type"), //$NON-NLS-1$ + IS_IN("is_in"), //$NON-NLS-1$ + LOCALITY("locality"), //$NON-NLS-1$ + + // POI + AMENITY("amenity"), //$NON-NLS-1$ + SHOP("shop"), //$NON-NLS-1$ + LANDUSE("landuse"), //$NON-NLS-1$ + OFFICE("office"), //$NON-NLS-1$ + EMERGENCY("emergency"), //$NON-NLS-1$ + MILITARY("military"), //$NON-NLS-1$ + ADMINISTRATIVE("administrative"), //$NON-NLS-1$ + MAN_MADE("man_made"), //$NON-NLS-1$ + BARRIER("barrier"), //$NON-NLS-1$ + LEISURE("leisure"), //$NON-NLS-1$ + TOURISM("tourism"), //$NON-NLS-1$ + SPORT("sport"), //$NON-NLS-1$ + HISTORIC("historic"), //$NON-NLS-1$ + NATURAL("natural"), //$NON-NLS-1$ + INTERNET_ACCESS("internet_access"), //$NON-NLS-1$ + + + CONTACT_WEBSITE("contact:website"), //$NON-NLS-1$ + CONTACT_PHONE("contact:phone"), //$NON-NLS-1$ + + OPENING_HOURS("opening_hours"), //$NON-NLS-1$ + PHONE("phone"), //$NON-NLS-1$ + DESCRIPTION("description"), //$NON-NLS-1$ + WEBSITE("website"), //$NON-NLS-1$ + URL("url"), //$NON-NLS-1$ + WIKIPEDIA("wikipedia"), //$NON-NLS-1$ + + ADMIN_LEVEL("admin_level"), //$NON-NLS-1$ + PUBLIC_TRANSPORT("public_transport") //$NON-NLS-1$ + ; + + private final String value; + private OSMTagKey(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + public enum OSMHighwayTypes { + TRUNK, MOTORWAY, PRIMARY, SECONDARY, RESIDENTIAL, TERTIARY, SERVICE, TRACK, + + // TODO is link needed? + TRUNK_LINK, MOTORWAY_LINK, PRIMARY_LINK, SECONDARY_LINK, RESIDENTIAL_LINK, TERTIARY_LINK, SERVICE_LINK, TRACK_LINK, + + } + + + public static boolean wayForCar(String tagHighway){ + if(tagHighway != null){ + String[] cars = new String[]{"trunk", "motorway", "primary", "secondary", "tertiary", "service", "residential", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + "trunk_link", "motorway_link", "primary_link", "secondary_link", "residential_link", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + "tertiary_link", "track", "unclassified" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + for(String c : cars){ + if(c.equals(tagHighway)){ + return true; + } + } + } + return false; + } +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java b/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java new file mode 100644 index 0000000000..b81e1411fd --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/OsmMapUtils.java @@ -0,0 +1,351 @@ +package net.osmand.osm.edit; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.osmand.data.LatLon; +import net.osmand.util.MapUtils; + +public class OsmMapUtils { + + public static double getDistance(Node e1, Node e2) { + return MapUtils.getDistance(e1.getLatitude(), e1.getLongitude(), e2.getLatitude(), e2.getLongitude()); + } + + public static double getDistance(Node e1, double latitude, double longitude) { + return MapUtils.getDistance(e1.getLatitude(), e1.getLongitude(), latitude, longitude); + } + + public static double getDistance(Node e1, LatLon point) { + return MapUtils.getDistance(e1.getLatitude(), e1.getLongitude(), point.getLatitude(), point.getLongitude()); + } + + public static LatLon getCenter(Entity e) { + if (e instanceof Node) { + return ((Node) e).getLatLon(); + } else if (e instanceof Way) { + return getWeightCenterForNodes(((Way) e).getNodes()); + } else if (e instanceof Relation) { + List list = new ArrayList(); + for (Entity fe : ((Relation) e).getMembers(null)) { + LatLon c = null; + // skip relations to avoid circular dependencies + if (!(fe instanceof Relation)) { + c = getCenter(fe); + } + if (c != null) { + list.add(c); + } + } + return getWeightCenter(list); + } + return null; + } + + public static LatLon getWeightCenter(Collection nodes) { + if (nodes.isEmpty()) { + return null; + } + double longitude = 0; + double latitude = 0; + for (LatLon n : nodes) { + longitude += n.getLongitude(); + latitude += n.getLatitude(); + } + return new LatLon(latitude / nodes.size(), longitude / nodes.size()); + } + + public static LatLon getWeightCenterForNodes(Collection nodes) { + if (nodes.isEmpty()) { + return null; + } + double longitude = 0; + double latitude = 0; + int count = 0; + for (Node n : nodes) { + if (n != null) { + count++; + longitude += n.getLongitude(); + latitude += n.getLatitude(); + } + } + if (count == 0) { + return null; + } + return new LatLon(latitude / count, longitude / count); + } + + public static LatLon getMathWeightCenterForNodes(Collection nodes) { + if (nodes.isEmpty()) { + return null; + } + double longitude = 0; + double latitude = 0; + double sumDist = 0; + Node prev = null; + for (Node n : nodes) { + if (n != null) { + if (prev == null) { + prev = n; + } else { + double dist = getDistance(prev, n); + sumDist += dist; + longitude += (prev.getLongitude() + n.getLongitude()) * dist / 2; + latitude += (n.getLatitude() + n.getLatitude()) * dist / 2; + prev = n; + } + } + } + if (sumDist == 0) { + if (prev == null) { + return null; + } + return prev.getLatLon(); + } + return new LatLon(latitude / sumDist, longitude / sumDist); + } + + public static void sortListOfEntities(List list, final double lat, final double lon) { + Collections.sort(list, new Comparator() { + @Override + public int compare(Entity o1, Entity o2) { + return Double.compare(MapUtils.getDistance(o1.getLatLon(), lat, lon), MapUtils.getDistance(o2.getLatLon(), lat, lon)); + } + }); + } + + public static void addIdsToList(Collection source, List ids) { + for (Entity e : source) { + ids.add(e.getId()); + } + } + + public static void simplifyDouglasPeucker(List n, int zoom, int epsilon, List result) { + if (zoom > 31) { + zoom = 31; + } + ArrayList l = new ArrayList(); + int first = 0; + int nsize = n.size(); + while (first < nsize) { + if (n.get(first) != null) { + break; + } + first++; + } + int last = nsize - 1; + while (last >= 0) { + if (n.get(last) != null) { + break; + } + last--; + } + if (last - first < 1) { + return; + } + // check for possible cycle + boolean checkCycle = true; + boolean cycle = false; + while (checkCycle && last > first) { + checkCycle = false; + + double x1 = MapUtils.getTileNumberX(zoom, n.get(first).getLongitude()); + double y1 = MapUtils.getTileNumberY(zoom, n.get(first).getLatitude()); + double x2 = MapUtils.getTileNumberX(zoom, n.get(last).getLongitude()); + double y2 = MapUtils.getTileNumberY(zoom, n.get(last).getLatitude()); + if (Math.abs(x1 - x2) + Math.abs(y1 - y2) < 0.001) { + last--; + cycle = true; + checkCycle = true; + } + } + if (last - first < 1) { + return; + } + simplifyDouglasPeucker(n, zoom, epsilon, l, first, last); + result.add(n.get(first)); + int lsize = l.size(); + for (int i = 0; i < lsize; i++) { + result.add(n.get(l.get(i))); + } + if (cycle) { + result.add(n.get(first)); + } + } + + private static void simplifyDouglasPeucker(List n, int zoom, int epsilon, List ints, int start, int end) { + double dmax = -1; + int index = -1; + for (int i = start + 1; i <= end - 1; i++) { + if (n.get(i) == null) { + continue; + } + double d = orthogonalDistance(zoom, n.get(start), n.get(end), n.get(i));// calculate distance from line + if (d > dmax) { + dmax = d; + index = i; + } + } + if (dmax >= epsilon) { + simplifyDouglasPeucker(n, zoom, epsilon, ints, start, index); + simplifyDouglasPeucker(n, zoom, epsilon, ints, index, end); + } else { + ints.add(end); + } + } + + private static double orthogonalDistance(int zoom, Node nodeLineStart, Node nodeLineEnd, Node node) { + LatLon p = MapUtils.getProjection(node.getLatitude(), node.getLongitude(), nodeLineStart.getLatitude(), + nodeLineStart.getLongitude(), nodeLineEnd.getLatitude(), nodeLineEnd.getLongitude()); + + double x1 = MapUtils.getTileNumberX(zoom, p.getLongitude()); + double y1 = MapUtils.getTileNumberY(zoom, p.getLatitude()); + double x2 = MapUtils.getTileNumberX(zoom, node.getLongitude()); + double y2 = MapUtils.getTileNumberY(zoom, node.getLatitude()); + double C = x2 - x1; + double D = y2 - y1; + return Math.sqrt(C * C + D * D); + } + + public static boolean isClockwiseWay(Way w) { + return isClockwiseWay(Collections.singletonList(w)); + } + + public static boolean isClockwiseWay(List ways) { + if (ways.isEmpty()) { + return true; + } + LatLon latLon = ways.get(0).getLatLon(); + double lat = latLon.getLatitude(); + double lon = 180; + double firstLon = -360; + boolean firstDirectionUp = false; + double previousLon = -360; + + double clockwiseSum = 0; + + Node prev = null; + boolean firstWay = true; + for (Way w : ways) { + List ns = w.getNodes(); + int startInd = 0; + int nssize = ns.size(); + if (firstWay && nssize > 0) { + prev = ns.get(0); + startInd = 1; + firstWay = false; + } + for (int i = startInd; i < nssize; i++) { + Node next = ns.get(i); + double rlon = ray_intersect_lon(prev, next, lat, lon); + if (rlon != -360d) { + boolean skipSameSide = (prev.getLatitude() <= lat) == (next.getLatitude() <= lat); + if (skipSameSide) { + continue; + } + boolean directionUp = prev.getLatitude() <= lat; + if (firstLon == -360) { + firstDirectionUp = directionUp; + firstLon = rlon; + } else { + boolean clockwise = (!directionUp) == (previousLon < rlon); + if (clockwise) { + clockwiseSum += Math.abs(previousLon - rlon); + } else { + clockwiseSum -= Math.abs(previousLon - rlon); + } + } + previousLon = rlon; + } + prev = next; + } + } + + if (firstLon != -360) { + boolean clockwise = (!firstDirectionUp) == (previousLon < firstLon); + if (clockwise) { + clockwiseSum += Math.abs(previousLon - firstLon); + } else { + clockwiseSum -= Math.abs(previousLon - firstLon); + } + } + + return clockwiseSum >= 0; + } + + // try to intersect from left to right + public static double ray_intersect_lon(Node node, Node node2, double latitude, double longitude) { + // a node below + Node a = node.getLatitude() < node2.getLatitude() ? node : node2; + // b node above + Node b = a == node2 ? node : node2; + if (latitude == a.getLatitude() || latitude == b.getLatitude()) { + latitude += 0.00000001d; + } + if (latitude < a.getLatitude() || latitude > b.getLatitude()) { + return -360d; + } else { + if (longitude < Math.min(a.getLongitude(), b.getLongitude())) { + return -360d; + } else { + if (a.getLongitude() == b.getLongitude() && longitude == a.getLongitude()) { + // the node on the boundary !!! + return longitude; + } + // that tested on all cases (left/right) + double lon = b.getLongitude() - (b.getLatitude() - latitude) * (b.getLongitude() - a.getLongitude()) + / (b.getLatitude() - a.getLatitude()); + if (lon <= longitude) { + return lon; + } else { + return -360d; + } + } + } + } + + /** + * Get the area (in m²) of a closed way, represented as a list of nodes + * + * @param nodes + * the list of nodes + * @return the area of it + */ + public static double getArea(List nodes) { + // x = longitude + // y = latitude + // calculate the reference point (lower left corner of the bbox) + // start with an arbitrary value, bigger than any lat or lon + double refX = 500, refY = 500; + for (Node n : nodes) { + if (n.getLatitude() < refY) + refY = n.getLatitude(); + if (n.getLongitude() < refX) + refX = n.getLongitude(); + } + + List xVal = new ArrayList(); + List yVal = new ArrayList(); + + for (Node n : nodes) { + // distance from bottom line to x coordinate of node + double xDist = MapUtils.getDistance(refY, refX, refY, n.getLongitude()); + // distance from left line to y coordinate of node + double yDist = MapUtils.getDistance(refY, refX, n.getLatitude(), refX); + + xVal.add(xDist); + yVal.add(yDist); + } + + double area = 0; + + for (int i = 1; i < xVal.size(); i++) { + area += xVal.get(i - 1) * yVal.get(i) - xVal.get(i) * yVal.get(i - 1); + } + + return Math.abs(area) / 2; + } +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/OsmTransportRoute.java b/OsmAnd-java/src/net/osmand/osm/edit/OsmTransportRoute.java new file mode 100644 index 0000000000..2e4e206a32 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/OsmTransportRoute.java @@ -0,0 +1,25 @@ +package net.osmand.osm.edit; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.osmand.data.TransportRoute; + +public class OsmTransportRoute extends TransportRoute { + private List ways; + + public List getWays() { + if(ways == null){ + return Collections.emptyList(); + } + return ways; + } + + public void addWay(Way w){ + if(ways == null){ + ways = new ArrayList(); + } + ways.add(w); + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/osm/edit/Relation.java b/OsmAnd-java/src/net/osmand/osm/edit/Relation.java new file mode 100644 index 0000000000..488d1a60c3 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/Relation.java @@ -0,0 +1,117 @@ +package net.osmand.osm.edit; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.osmand.data.LatLon; + +public class Relation extends Entity { + + // lazy loading + Map members = null; + Map memberEntities = null; + + + public Relation(long id) { + super(id); + } + + public void addMember(Long id, EntityType type, String role){ + if(members == null){ + members = new LinkedHashMap(); + } + members.put(new EntityId(type, id), role); + } + + public String removeMember(EntityType e, Long id){ + if(members == null){ + return null; + } + return members.remove(id); + } + + public String getRole(Entity e){ + return members.get(e.getId()); + } + + public String getRole(Long id){ + return members.get(id); + } + + public Collection getMemberIds() { + return getMemberIds(null); + } + + public Map getMembersMap() { + if(members == null){ + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(members); + } + + public Collection getMemberIds(String role) { + if (members == null) { + return Collections.emptyList(); + } + if (role == null) { + return members.keySet(); + } + List l = new ArrayList(); + for (EntityId m : members.keySet()) { + if (role.equals(members.get(m))) { + l.add(m); + } + } + return l; + } + + public Map getMemberEntities() { + if(memberEntities == null){ + return Collections.emptyMap(); + } + return memberEntities; + } + + public Collection getMembers(String role) { + if (memberEntities == null) { + return Collections.emptyList(); + } + if (role == null) { + return memberEntities.keySet(); + } + List l = new ArrayList(); + for (Entity m : memberEntities.keySet()) { + if (role.equals(memberEntities.get(m))) { + l.add(m); + } + } + return l; + } + + @Override + public void initializeLinks(Map entities){ + if (members != null) { + if(memberEntities == null){ + memberEntities = new LinkedHashMap(); + } else { + memberEntities.clear(); + } + for(EntityId l : members.keySet()){ + if(l != null && entities.get(l) != null){ + memberEntities.put(entities.get(l), members.get(l)); + } + } + } + } + + + @Override + public LatLon getLatLon() { + return null; + } + +} diff --git a/OsmAnd-java/src/net/osmand/osm/edit/Way.java b/OsmAnd-java/src/net/osmand/osm/edit/Way.java new file mode 100644 index 0000000000..9564383768 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/edit/Way.java @@ -0,0 +1,145 @@ +package net.osmand.osm.edit; + +import gnu.trove.list.array.TLongArrayList; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import net.osmand.data.LatLon; + +public class Way extends Entity { + + // lazy loading + private TLongArrayList nodeIds = null; + private List nodes = null; + + public Way(long id) { + super(id); + } + + public Way(Way w) { + super(w.getId()); + if (w.nodeIds != null) { + nodeIds = new TLongArrayList(w.nodeIds); + } + if (w.nodes != null) { + nodes = new ArrayList(w.nodes); + } + } + + public Way(long id, List nodes) { + super(id); + this.nodes = new ArrayList(nodes); + nodeIds = new TLongArrayList(nodes.size()); + for (Node n : nodes) { + nodeIds.add(n.getId()); + } + } + + public void addNode(long id){ + if(nodeIds == null){ + nodeIds = new TLongArrayList(); + } + nodeIds.add(id); + } + + public long getFirstNodeId(){ + if(nodeIds == null){ + return -1; + } + return nodeIds.get(0); + } + + public long getLastNodeId(){ + if(nodeIds == null){ + return -1; + } + return nodeIds.get(nodeIds.size() - 1); + } + + public void addNode(Node n){ + if(nodeIds == null){ + nodeIds = new TLongArrayList(); + } + if(nodes == null){ + nodes = new ArrayList(); + } + nodeIds.add(n.getId()); + nodes.add(n); + } + + public void addNode(Node n, int index){ + if(nodeIds == null){ + nodeIds = new TLongArrayList(); + } + if(nodes == null){ + nodes = new ArrayList(); + } + nodeIds.insert(index, n.getId()); + nodes.add(index, n); + } + + public long removeNodeByIndex(int i){ + if(nodeIds == null){ + return -1; + } + long toReturn = nodeIds.removeAt(i); + if(nodes != null && nodes.size() > i){ + nodes.remove(i); + } + return toReturn; + } + + public TLongArrayList getNodeIds(){ + if(nodeIds == null){ + return new TLongArrayList(0); + } + return nodeIds; + } + + public List getEntityIds(){ + if(nodeIds == null){ + return Collections.emptyList(); + } + List ls = new ArrayList(); + for (int i = 0; i < nodeIds.size(); i++) { + ls.add(new EntityId(EntityType.NODE, nodeIds.get(i))); + } + return ls; + } + + public List getNodes() { + if(nodes == null){ + return Collections.emptyList(); + } + return nodes; + } + + @Override + public void initializeLinks(Map entities) { + if (nodeIds != null) { + if(nodes == null){ + nodes = new ArrayList(); + } else { + nodes.clear(); + } + int nIsize = nodeIds.size(); + for (int i = 0; i < nIsize; i++) { + nodes.add((Node) entities.get(new EntityId(EntityType.NODE,nodeIds.get(i)))); + } + } + } + + @Override + public LatLon getLatLon() { + if(nodes == null){ + return null; + } + return OsmMapUtils.getWeightCenterForNodes(nodes); + } + + + +} diff --git a/OsmAnd-java/src/net/osmand/osm/io/Base64.java b/OsmAnd-java/src/net/osmand/osm/io/Base64.java new file mode 100644 index 0000000000..49854f313d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/io/Base64.java @@ -0,0 +1,93 @@ +package net.osmand.osm.io; + +/** + * @source http://www.javaworld.com/javaworld/javatips/jw-javatip47.html -- 24.11.2008, (mb) + */ +public class Base64 { + /******************************************************************************************************************* + * BASE 64 encoding of a String or an array of bytes. See also RFC 1421. + * + * @author Unknown + * @author David W. Croft + * @version 1998-06-08 + ******************************************************************************************************************/ + + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7 + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15 + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23 + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31 + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39 + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47 + 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55 + '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63 + + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + + public static String encode(final String s) + ////////////////////////////////////////////////////////////////////// + { + return encode(s.getBytes()); + } + + public static String encode(final byte[] octetString) + ////////////////////////////////////////////////////////////////////// + { + int bits24; + int bits6; + + final char[] out = new char[((octetString.length - 1) / 3 + 1) * 4]; + + int outIndex = 0; + int i = 0; + + while ((i + 3) <= octetString.length) { + // store the octets + bits24 = (octetString[i++] & 0xFF) << 16; + bits24 |= (octetString[i++] & 0xFF) << 8; + bits24 |= (octetString[i++] & 0xFF) << 0; + + bits6 = (bits24 & 0x00FC0000) >> 18; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0003F000) >> 12; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x00000FC0) >> 6; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0000003F); + out[outIndex++] = alphabet[bits6]; + } + + if (octetString.length - i == 2) { + // store the octets + bits24 = (octetString[i] & 0xFF) << 16; + bits24 |= (octetString[i + 1] & 0xFF) << 8; + + bits6 = (bits24 & 0x00FC0000) >> 18; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0003F000) >> 12; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x00000FC0) >> 6; + out[outIndex++] = alphabet[bits6]; + + // padding + out[outIndex++] = '='; + } else if (octetString.length - i == 1) { + // store the octets + bits24 = (octetString[i] & 0xFF) << 16; + + bits6 = (bits24 & 0x00FC0000) >> 18; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0003F000) >> 12; + out[outIndex++] = alphabet[bits6]; + + // padding + out[outIndex++] = '='; + out[outIndex++] = '='; + } + + return new String(out); + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/osm/io/IOsmStorageFilter.java b/OsmAnd-java/src/net/osmand/osm/io/IOsmStorageFilter.java new file mode 100644 index 0000000000..b567aece95 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/io/IOsmStorageFilter.java @@ -0,0 +1,10 @@ +package net.osmand.osm.io; + +import net.osmand.osm.edit.Entity; +import net.osmand.osm.edit.Entity.EntityId; + +public interface IOsmStorageFilter { + + public boolean acceptEntityToLoad(OsmBaseStorage storage, EntityId entityId, Entity entity); + +} diff --git a/OsmAnd-java/src/net/osmand/osm/io/NetworkUtils.java b/OsmAnd-java/src/net/osmand/osm/io/NetworkUtils.java new file mode 100644 index 0000000000..f74da15963 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/io/NetworkUtils.java @@ -0,0 +1,154 @@ +package net.osmand.osm.io; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Map; +import java.util.zip.GZIPOutputStream; + +import net.osmand.PlatformUtil; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + +public class NetworkUtils { + private static final Log log = PlatformUtil.getLog(NetworkUtils.class); + public static String sendGetRequest(String urlText, String userNamePassword){ + URL url; + try { + log.info("GET : " + urlText); + url = new URL(urlText); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(false); + conn.setRequestMethod("GET"); + if(userNamePassword != null) { + conn.setRequestProperty("Authorization", "Basic " + Base64.encode(userNamePassword)); //$NON-NLS-1$ //$NON-NLS-2$ + } + + conn.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$ + log.info("Response code and message : " + conn.getResponseCode() + " " + conn.getResponseMessage()); + if(conn.getResponseCode() != 200){ + return conn.getResponseMessage(); + } + InputStream is = conn.getInputStream(); + StringBuilder responseBody = new StringBuilder(); + if (is != null) { + BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$ + String s; + boolean first = true; + while ((s = in.readLine()) != null) { + if(first){ + first = false; + } else { + responseBody.append("\n"); //$NON-NLS-1$ + } + responseBody.append(s); + + } + is.close(); + } + String response = responseBody.toString(); + log.info("Response : " + response); + if(response.startsWith("OK")){ + return null; + } + return response; + } catch (IOException e) { + log.error(e.getMessage(), e); + return e.getMessage(); + } + } + + private static final String BOUNDARY = "CowMooCowMooCowCowCow"; //$NON-NLS-1$ + public static String uploadFile(String urlText, File fileToUpload, String userNamePassword, String formName, boolean gzip, Map additionalMapData){ + URL url; + try { + boolean firstPrm =!urlText.contains("?"); + for (String key : additionalMapData.keySet()) { + urlText += (firstPrm ? "?" : "&") + key + "=" + URLEncoder.encode(additionalMapData.get(key), "UTF-8"); + firstPrm = false; + } + log.info("Start uploading file to " + urlText + " " +fileToUpload.getName()); + url = new URL(urlText); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestMethod("POST"); + if(userNamePassword != null) { + conn.setRequestProperty("Authorization", "Basic " + Base64.encode(userNamePassword)); //$NON-NLS-1$ //$NON-NLS-2$ + } + + conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //$NON-NLS-1$ //$NON-NLS-2$ + conn.setRequestProperty("User-Agent", "OsmAnd"); //$NON-NLS-1$ //$NON-NLS-2$ + + OutputStream ous = conn.getOutputStream(); +// for (String key : additionalMapData.keySet()) { +// ous.write(("--" + BOUNDARY + "\r\n").getBytes()); +// ous.write(("content-disposition: form-data; name=\"" + key + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ +// ous.write((additionalMapData.get(key) + "\r\n").getBytes()); +// } + ous.write(("--" + BOUNDARY+"\r\n").getBytes()); + String filename = fileToUpload.getName(); + if(gzip){ + filename+=".gz"; + } + ous.write(("content-disposition: form-data; name=\""+formName+"\"; filename=\"" + filename + "\"\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes()); //$NON-NLS-1$ + InputStream fis = new FileInputStream(fileToUpload); + BufferedInputStream bis = new BufferedInputStream(fis, 20 * 1024); + ous.flush(); + if(gzip){ + GZIPOutputStream gous = new GZIPOutputStream(ous, 1024); + Algorithms.streamCopy(bis, gous); + gous.flush(); + gous.finish(); + } else { + Algorithms.streamCopy(bis, ous); + } + + ous.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); //$NON-NLS-1$ //$NON-NLS-2$ + ous.flush(); + Algorithms.closeStream(bis); + Algorithms.closeStream(ous); + + log.info("Finish uploading file " + fileToUpload.getName()); + log.info("Response code and message : " + conn.getResponseCode() + " " + conn.getResponseMessage()); + if(conn.getResponseCode() != 200){ + return conn.getResponseMessage(); + } + InputStream is = conn.getInputStream(); + StringBuilder responseBody = new StringBuilder(); + if (is != null) { + BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8")); //$NON-NLS-1$ + String s; + boolean first = true; + while ((s = in.readLine()) != null) { + if(first){ + first = false; + } else { + responseBody.append("\n"); //$NON-NLS-1$ + } + responseBody.append(s); + + } + is.close(); + } + String response = responseBody.toString(); + log.info("Response : " + response); + return null; + } catch (IOException e) { + log.error(e.getMessage(), e); + return e.getMessage(); + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/osm/io/OsmBaseStorage.java b/OsmAnd-java/src/net/osmand/osm/io/OsmBaseStorage.java new file mode 100644 index 0000000000..b0a6992614 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/io/OsmBaseStorage.java @@ -0,0 +1,295 @@ +package net.osmand.osm.io; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import net.osmand.IProgress; +import net.osmand.osm.edit.Entity; +import net.osmand.osm.edit.EntityInfo; +import net.osmand.osm.edit.Node; +import net.osmand.osm.edit.Relation; +import net.osmand.osm.edit.Way; +import net.osmand.osm.edit.Entity.EntityId; +import net.osmand.osm.edit.Entity.EntityType; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + + +public class OsmBaseStorage extends DefaultHandler { + + protected static final String ELEM_OSM = "osm"; //$NON-NLS-1$ + protected static final String ELEM_NODE = "node"; //$NON-NLS-1$ + protected static final String ELEM_TAG = "tag"; //$NON-NLS-1$ + protected static final String ELEM_WAY = "way"; //$NON-NLS-1$ + protected static final String ELEM_ND = "nd"; //$NON-NLS-1$ + protected static final String ELEM_RELATION = "relation"; //$NON-NLS-1$ + protected static final String ELEM_MEMBER = "member"; //$NON-NLS-1$ + + + protected static final String ATTR_VERSION = "version"; //$NON-NLS-1$ + protected static final String ATTR_ID = "id"; //$NON-NLS-1$ + protected static final String ATTR_LAT = "lat"; //$NON-NLS-1$ + protected static final String ATTR_LON = "lon"; //$NON-NLS-1$ + protected static final String ATTR_TIMESTAMP = "timestamp"; //$NON-NLS-1$ + protected static final String ATTR_UID = "uid"; //$NON-NLS-1$ + protected static final String ATTR_USER = "user"; //$NON-NLS-1$ + protected static final String ATTR_VISIBLE = "visible"; //$NON-NLS-1$ + protected static final String ATTR_CHANGESET = "changeset"; //$NON-NLS-1$ + protected static final String ATTR_K = "k"; //$NON-NLS-1$ + protected static final String ATTR_V = "v"; //$NON-NLS-1$ + + protected static final String ATTR_TYPE = "type"; //$NON-NLS-1$ + protected static final String ATTR_REF = "ref"; //$NON-NLS-1$ + protected static final String ATTR_ROLE = "role"; //$NON-NLS-1$ + + protected Entity currentParsedEntity = null; + protected EntityInfo currentParsedEntityInfo = null; + + protected boolean parseStarted; + + protected Map entities = new LinkedHashMap(); + protected Map entityInfo = new LinkedHashMap(); + + // this is used to show feedback to user + protected int progressEntity = 0; + protected IProgress progress; + protected InputStream inputStream; + protected InputStream streamForProgress; + protected List filters = new ArrayList(); + protected boolean supressWarnings = true; + protected boolean parseEntityInfo; + + + + public synchronized void parseOSM(InputStream stream, IProgress progress, InputStream streamForProgress, + boolean entityInfo) throws IOException, SAXException { + this.inputStream = stream; + this.progress = progress; + parseEntityInfo = entityInfo; + if(streamForProgress == null){ + streamForProgress = inputStream; + } + this.streamForProgress = streamForProgress; + SAXParser parser = initSaxParser(); + parseStarted = false; + entities.clear(); + this.entityInfo.clear(); + if(progress != null){ + progress.startWork(streamForProgress.available()); + } + + parser.parse(stream, this); + if(progress != null){ + progress.finishTask(); + } + completeReading(); + } + + /** + * @param stream + * @throws IOException + * @throws SAXException - could be + */ + public synchronized void parseOSM(InputStream stream, IProgress progress) throws IOException, SAXException { + parseOSM(stream, progress, null, true); + + } + + public boolean isSupressWarnings() { + return supressWarnings; + } + public void setSupressWarnings(boolean supressWarnings) { + this.supressWarnings = supressWarnings; + } + + protected SAXParser saxParser; + public SAXParser initSaxParser(){ + if(saxParser != null){ + return saxParser; + } + SAXParserFactory factory = SAXParserFactory.newInstance(); + try { + factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false); //$NON-NLS-1$ + return saxParser = factory.newSAXParser(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException(e); + } catch (SAXException e) { + throw new IllegalStateException(e); + } + } + + protected Long parseId(Attributes a, String name, long defId){ + long id = defId; + String value = a.getValue(name); + try { + id = Long.parseLong(value); + } catch (NumberFormatException e) { + } + return id; + } + + protected double parseDouble(Attributes a, String name, double defVal){ + double ret = defVal; + String value = a.getValue(name); + try { + ret = Double.parseDouble(value); + } catch (NumberFormatException e) { + } + return ret; + } + + protected static final Set supportedVersions = new HashSet(); + static { + supportedVersions.add("0.6"); //$NON-NLS-1$ + supportedVersions.add("0.5"); //$NON-NLS-1$ + } + + protected void initRootElement(String uri, String localName, String name, Attributes attributes) throws OsmVersionNotSupported{ + if(!ELEM_OSM.equals(name) || !supportedVersions.contains(attributes.getValue(ATTR_VERSION))){ + throw new OsmVersionNotSupported(); + } + parseStarted = true; + } + + protected static final int moduleProgress = 1 << 10; + + @Override + public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { + name = saxParser.isNamespaceAware() ? localName : name; + if(!parseStarted){ + initRootElement(uri, localName, name, attributes); + } + if (currentParsedEntity == null) { + progressEntity ++; + if(progress != null && ((progressEntity % moduleProgress) == 0) && + !progress.isIndeterminate() && streamForProgress != null){ + try { + progress.remaining(streamForProgress.available()); + } catch (IOException e) { + progress.startWork(-1); + } + } + if (ELEM_NODE.equals(name)) { + currentParsedEntity = new Node(parseDouble(attributes, ATTR_LAT, 0), parseDouble(attributes, ATTR_LON, 0), + parseId(attributes, ATTR_ID, -1)); + } else if (ELEM_WAY.equals(name)) { + currentParsedEntity = new Way(parseId(attributes, ATTR_ID, -1)); + } else if (ELEM_RELATION.equals(name)) { + currentParsedEntity = new Relation(parseId(attributes, ATTR_ID, -1)); + } else { + // this situation could be logged as unhandled + } + if(parseEntityInfo && currentParsedEntity != null){ + currentParsedEntityInfo = new EntityInfo(); + currentParsedEntityInfo.setChangeset(attributes.getValue(ATTR_CHANGESET)); + currentParsedEntityInfo.setTimestamp(attributes.getValue(ATTR_TIMESTAMP)); + currentParsedEntityInfo.setUser(attributes.getValue(ATTR_USER)); + currentParsedEntityInfo.setVersion(attributes.getValue(ATTR_VERSION)); + currentParsedEntityInfo.setVisible(attributes.getValue(ATTR_VISIBLE)); + currentParsedEntityInfo.setUid(attributes.getValue(ATTR_UID)); + } + } else { + if (ELEM_TAG.equals(name)) { + String key = attributes.getValue(ATTR_K); + if(key != null){ + currentParsedEntity.putTag(key, attributes.getValue(ATTR_V)); + } + } else if (ELEM_ND.equals(name)) { + Long id = parseId(attributes, ATTR_REF, -1); + if(id != -1 && currentParsedEntity instanceof Way){ + ((Way)currentParsedEntity).addNode(id); + } + } else if (ELEM_MEMBER.equals(name)) { + Long id = parseId(attributes, ATTR_REF, -1); + if(id != -1 && currentParsedEntity instanceof Relation){ + EntityType type = EntityType.valueOf(attributes.getValue(ATTR_TYPE).toUpperCase()); + ((Relation)currentParsedEntity).addMember(id, type, attributes.getValue(ATTR_ROLE)); + } + + } else { + // this situation could be logged as unhandled + } + } + } + + @Override + public void endElement(String uri, String localName, String name) throws SAXException { + name = saxParser.isNamespaceAware() ? localName : name; + EntityType type = null; + if (ELEM_NODE.equals(name)){ + type = EntityType.NODE; + } else if (ELEM_WAY.equals(name)){ + type = EntityType.WAY; + } else if (ELEM_RELATION.equals(name)){ + type = EntityType.RELATION; + } + if (type != null) { + if(currentParsedEntity != null){ + EntityId entityId = new EntityId(type, currentParsedEntity.getId()); + if(acceptEntityToLoad(entityId, currentParsedEntity)){ + Entity oldEntity = entities.put(entityId, currentParsedEntity); + if(parseEntityInfo && currentParsedEntityInfo != null){ + entityInfo.put(entityId, currentParsedEntityInfo); + } + if(!supressWarnings && oldEntity!= null){ + throw new UnsupportedOperationException("Entity with id=" + oldEntity.getId() +" is duplicated in osm map"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } else { +// System.gc(); + } + currentParsedEntity = null; + } + } + super.endElement(uri, localName, name); + } + + + protected boolean acceptEntityToLoad(EntityId entityId, Entity entity) { + for(IOsmStorageFilter f : filters){ + if(!f.acceptEntityToLoad(this, entityId, entity)){ + return false; + } + } + return true; + } + + public void completeReading(){ + for(Entity e : entities.values()){ + e.initializeLinks(entities); + } + } + + public Map getRegisteredEntityInfo() { + return entityInfo; + } + + public Map getRegisteredEntities() { + return entities; + } + + public List getFilters() { + return filters; + } + + + /** + * Thrown when version is not supported + */ + public static class OsmVersionNotSupported extends SAXException { + private static final long serialVersionUID = -127558215143984838L; + + } + +} diff --git a/OsmAnd-java/src/net/osmand/osm/rendering_types.xml b/OsmAnd-java/src/net/osmand/osm/rendering_types.xml new file mode 100644 index 0000000000..eba05d5856 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/osm/rendering_types.xml @@ -0,0 +1,831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd-java/src/net/osmand/plus/ApplicationMode.java b/OsmAnd-java/src/net/osmand/plus/ApplicationMode.java new file mode 100644 index 0000000000..589b040fcb --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/ApplicationMode.java @@ -0,0 +1,23 @@ +package net.osmand.plus; + + +public enum ApplicationMode { + /* + * DEFAULT("Default"), CAR("Car"), BICYCLE("Bicycle"), PEDESTRIAN("Pedestrian"); + */ + DEFAULT(R.string.app_mode_default), + CAR(R.string.app_mode_car), + BICYCLE(R.string.app_mode_bicycle), + PEDESTRIAN(R.string.app_mode_pedestrian); + + private final int key; + + ApplicationMode(int key) { + this.key = key; + } + + public String toHumanString(ClientContext ctx) { + return ctx.getString(key); + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/ClientContext.java b/OsmAnd-java/src/net/osmand/plus/ClientContext.java new file mode 100644 index 0000000000..558828e037 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/ClientContext.java @@ -0,0 +1,54 @@ +package net.osmand.plus; + +import java.io.File; + +import net.osmand.Location; +import net.osmand.plus.api.ExternalServiceAPI; +import net.osmand.plus.api.InternalOsmAndAPI; +import net.osmand.plus.api.InternalToDoAPI; +import net.osmand.plus.api.SQLiteAPI; +import net.osmand.plus.api.SettingsAPI; +import net.osmand.plus.render.RendererRegistry; +import net.osmand.plus.routing.RoutingHelper; + + +/* + * In Android version ClientContext should be cast to Android.Context for backward compatibility + */ +public interface ClientContext { + + public String getString(int resId, Object... args); + + public File getAppPath(String extend); + + public void showShortToastMessage(int msgId, Object... args); + + public void showToastMessage(int msgId, Object... args); + + public void showToastMessage(String msg); + + public RendererRegistry getRendererRegistry(); + + public OsmandSettings getSettings(); + + public SettingsAPI getSettingsAPI(); + + public ExternalServiceAPI getExternalServiceAPI(); + + public InternalToDoAPI getTodoAPI(); + + public InternalOsmAndAPI getInternalAPI(); + + public SQLiteAPI getSQLiteAPI(); + + // public RendererAPI getRendererAPI(); + + public void runInUIThread(Runnable run); + + public void runInUIThread(Runnable run, long delay); + + public RoutingHelper getRoutingHelper(); + + public Location getLastKnownLocation(); + +} diff --git a/OsmAnd-java/src/net/osmand/plus/CurrentPositionHelper.java b/OsmAnd-java/src/net/osmand/plus/CurrentPositionHelper.java new file mode 100644 index 0000000000..3618e7e5d8 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/CurrentPositionHelper.java @@ -0,0 +1,120 @@ +package net.osmand.plus; + +import java.io.IOException; + +import net.osmand.Location; +import net.osmand.binary.RouteDataObject; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.router.GeneralRouter.GeneralRouterProfile; +import net.osmand.router.RoutePlannerFrontEnd; +import net.osmand.router.RoutingConfiguration; +import net.osmand.router.RoutingContext; +import net.osmand.util.MapUtils; + +public class CurrentPositionHelper { + + private RouteDataObject lastFound; + private Location lastAskedLocation = null; + private Thread calculatingThread = null; + private RoutingContext ctx; + private ClientContext app; + private ApplicationMode am; + + public CurrentPositionHelper(ClientContext app) { + this.app = app; + } + + private void initCtx(ClientContext app) { + am = app.getSettings().getApplicationMode(); + GeneralRouterProfile p ; + if (am == ApplicationMode.BICYCLE) { + p = GeneralRouterProfile.BICYCLE; + } else if (am == ApplicationMode.PEDESTRIAN) { + p = GeneralRouterProfile.PEDESTRIAN; + } else { + p = GeneralRouterProfile.CAR; + } + RoutingConfiguration cfg = RoutingConfiguration.getDefault().build(p.name().toLowerCase(), 10); + ctx = new RoutingContext(cfg, null, app.getTodoAPI().getRoutingMapFiles()); + } + + private RouteDataObject runUpdateInThread(Location loc) { + RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(false); + try { + if(ctx == null || am != app.getSettings().getApplicationMode()) { + initCtx(app); + } + RouteSegment sg = rp.findRouteSegment(loc.getLatitude(), loc.getLongitude(), ctx); + if(sg == null) { + return null; + } + return sg.getRoad(); + } catch (IOException e) { + return null; + } + } + + + private void scheduleRouteSegmentFind(final Location loc){ + if(calculatingThread == Thread.currentThread()) { + lastFound = runUpdateInThread(loc); + } else if(calculatingThread == null && loc != null) { + Runnable run = new Runnable() { + @Override + public void run() { + try { + lastFound = runUpdateInThread(loc); + if (lastAskedLocation != loc) { + // refresh and run new task if needed + getLastKnownRouteSegment(lastAskedLocation); + } + } finally { + calculatingThread = null; + } + } + }; + calculatingThread = app.getRoutingHelper().startTaskInRouteThreadIfPossible(run); + } + + } + + private static double getOrthogonalDistance(RouteDataObject r, Location loc){ + double d = 1000; + if (r.getPointsLength() > 0) { + double pLt = MapUtils.get31LatitudeY(r.getPoint31YTile(0)); + double pLn = MapUtils.get31LongitudeX(r.getPoint31XTile(0)); + for (int i = 1; i < r.getPointsLength(); i++) { + double lt = MapUtils.get31LatitudeY(r.getPoint31YTile(i)); + double ln = MapUtils.get31LongitudeX(r.getPoint31XTile(i)); + double od = MapUtils.getOrthogonalDistance(loc.getLatitude(), loc.getLongitude(), pLt, pLn, lt, ln); + if (od < d) { + d = od; + } + pLt = lt; + pLn = ln; + } + } + return d; + } + + public RouteDataObject getLastKnownRouteSegment(Location loc) { + lastAskedLocation = loc; + RouteDataObject r = lastFound; + if (loc == null || loc.getAccuracy() > 50) { + return null; + } + if (r == null) { + scheduleRouteSegmentFind(loc); + return null; + } + double d = getOrthogonalDistance(r, loc); + if (d > 25) { + scheduleRouteSegmentFind(loc); + } + if (d < 70) { + return r; + } + return null; + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/FavouritesDbHelper.java b/OsmAnd-java/src/net/osmand/plus/FavouritesDbHelper.java new file mode 100644 index 0000000000..25eebff4a0 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/FavouritesDbHelper.java @@ -0,0 +1,331 @@ +package net.osmand.plus; + +import java.io.File; +import java.text.Collator; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import net.osmand.PlatformUtil; +import net.osmand.data.FavouritePoint; +import net.osmand.plus.GPXUtilities.GPXFile; +import net.osmand.plus.GPXUtilities.WptPt; +import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; +import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; + +public class FavouritesDbHelper { + + private static final int DATABASE_VERSION = 2; + private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(FavouritesDbHelper.class); + public static final String FAVOURITE_DB_NAME = "favourite"; //$NON-NLS-1$ + private static final String FAVOURITE_TABLE_NAME = "favourite"; //$NON-NLS-1$ + private static final String FAVOURITE_COL_NAME = "name"; //$NON-NLS-1$ + private static final String FAVOURITE_COL_CATEGORY = "category"; //$NON-NLS-1$ + private static final String FAVOURITE_COL_LAT = "latitude"; //$NON-NLS-1$ + private static final String FAVOURITE_COL_LON = "longitude"; //$NON-NLS-1$ + private static final String FAVOURITE_TABLE_CREATE = "CREATE TABLE " + FAVOURITE_TABLE_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$ + FAVOURITE_COL_NAME + " TEXT, " + FAVOURITE_COL_CATEGORY + " TEXT, " + //$NON-NLS-1$ //$NON-NLS-2$ + FAVOURITE_COL_LAT + " double, " + FAVOURITE_COL_LON + " double);"; //$NON-NLS-1$ //$NON-NLS-2$ + + public static final String FILE_TO_SAVE = "favourites.gpx"; //$NON-NLS-1$ + public static final String FILE_TO_BACKUP = "favourites_bak.gpx"; //$NON-NLS-1$ + + // externalize ? + private static final String GPX_GROUP = "Gpx"; + + private List favoritePointsFromGPXFile = null; + private List cachedFavoritePoints = new ArrayList(); + private Map> favoriteGroups = null; + private final ClientContext context; + private SQLiteConnection conn; + + public FavouritesDbHelper(ClientContext context) { + this.context = context; + } + + private SQLiteConnection openConnection(boolean readonly) { + conn = context.getSQLiteAPI().getOrCreateDatabase(FAVOURITE_DB_NAME, readonly); + if (conn.getVersion() == 0 || DATABASE_VERSION != conn.getVersion()) { + if (readonly) { + conn.close(); + conn = context.getSQLiteAPI().getOrCreateDatabase(FAVOURITE_DB_NAME, readonly); + } + if (conn.getVersion() == 0) { + conn.setVersion(DATABASE_VERSION); + onCreate(conn); + } else { + onUpgrade(conn, conn.getVersion(), DATABASE_VERSION); + } + + } + return conn; + } + + public void onCreate(SQLiteConnection db) { + db.execSQL(FAVOURITE_TABLE_CREATE); + createCategories(db); + } + + public void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { + if(oldVersion == 1){ + db.execSQL("ALTER TABLE " + FAVOURITE_TABLE_NAME + " ADD " + FAVOURITE_COL_CATEGORY + " text"); + createCategories(db); + db.execSQL("UPDATE " + FAVOURITE_TABLE_NAME + " SET category = ?", new Object[] { context.getString(R.string.favorite_default_category)}); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + public void backupSilently() { + try { + exportFavorites(FILE_TO_BACKUP); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + + public String exportFavorites() { + return exportFavorites(FILE_TO_SAVE); + } + + public String exportFavorites(String fileName) { + File f = new File(context.getAppPath(null), fileName); + GPXFile gpx = new GPXFile(); + for (FavouritePoint p : getFavouritePoints()) { + if (p.isStored()) { + WptPt pt = new WptPt(); + pt.lat = p.getLatitude(); + pt.lon = p.getLongitude(); + pt.name = p.getName(); + if (p.getCategory().length() > 0) + pt.category = p.getCategory(); + gpx.points.add(pt); + } + } + return GPXUtilities.writeGpxFile(f, gpx, context); + } + + private void createCategories(SQLiteConnection db){ + addCategoryQuery(context.getString(R.string.favorite_home_category), db); + addCategoryQuery(context.getString(R.string.favorite_friends_category), db); + addCategoryQuery(context.getString(R.string.favorite_places_category), db); + addCategoryQuery(context.getString(R.string.favorite_default_category), db); + } + + public List getFavoritePointsFromGPXFile() { + return favoritePointsFromGPXFile; + } + + public void setFavoritePointsFromGPXFile(List favoritePointsFromGPXFile) { + this.favoritePointsFromGPXFile = favoritePointsFromGPXFile; + if(favoritePointsFromGPXFile == null){ + favoriteGroups.remove(GPX_GROUP); + } else { + checkFavoritePoints(); + for(FavouritePoint t : favoritePointsFromGPXFile){ + t.setCategory(GPX_GROUP); + t.setStored(false); + } + favoriteGroups.put(GPX_GROUP, favoritePointsFromGPXFile); + } + recalculateCachedFavPoints(); + } + + public void addFavoritePointToGPXFile(FavouritePoint fp) { + fp.setCategory(GPX_GROUP); + fp.setStored(false); + if (!favoriteGroups.containsKey(GPX_GROUP)) { + favoriteGroups.put(GPX_GROUP, new ArrayList()); + } + favoriteGroups.get(GPX_GROUP).add(fp); + recalculateCachedFavPoints(); + } + + public List getFavouritePoints() { + checkFavoritePoints(); + return cachedFavoritePoints; + } + + public Map> getFavoriteGroups() { + checkFavoritePoints(); + return favoriteGroups; + } + + + public boolean editFavouriteName(FavouritePoint p, String newName, String category) { + checkFavoritePoints(); + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String oldCategory = p.getCategory(); + db.execSQL( + "UPDATE " + FAVOURITE_TABLE_NAME + " SET " + FAVOURITE_COL_NAME + " = ?, " + FAVOURITE_COL_CATEGORY + "= ? WHERE " + whereNameLatLon(), new Object[] { newName, category, p.getName(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + p.setName(newName); + p.setCategory(category); + if (!oldCategory.equals(category)) { + favoriteGroups.get(oldCategory).remove(p); + if (!favoriteGroups.containsKey(category)) { + addCategoryQuery(category, db); + favoriteGroups.put(category, new ArrayList()); + } + favoriteGroups.get(category).add(p); + } + }finally { + db.close(); + } + return true; + } + return false; + } + + private String whereNameLatLon() { + String singleFavourite = " " + FAVOURITE_COL_NAME + "= ? AND " + FAVOURITE_COL_LAT + " = ? AND " + FAVOURITE_COL_LON + " = ?"; + return singleFavourite; + } + + public boolean editFavourite(FavouritePoint p, double lat, double lon) { + checkFavoritePoints(); + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL( + "UPDATE " + FAVOURITE_TABLE_NAME + " SET latitude = ?, longitude = ? WHERE " + whereNameLatLon(), new Object[] { lat, lon, p.getName(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + p.setLatitude(lat); + p.setLongitude(lon); + backupSilently(); + } finally { + db.close(); + } + return true; + } + return false; + } + + private FavouritePoint findFavoriteByAllProperties(String category, String name, double lat, double lon){ + if (favoriteGroups.containsKey(category)) { + for (FavouritePoint fv : favoriteGroups.get(category)) { + if (name.equals(fv.getName()) && (lat == fv.getLatitude()) && (lon == fv.getLongitude())) { + return fv; + } + } + } + return null; + } + + public boolean deleteFavourite(FavouritePoint p) { + checkFavoritePoints(); + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL( + "DELETE FROM " + FAVOURITE_TABLE_NAME + " WHERE category = ? AND " + whereNameLatLon(), new Object[] { p.getCategory(), p.getName(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + FavouritePoint fp = findFavoriteByAllProperties(p.getCategory(), p.getName(), p.getLatitude(), p.getLongitude()); + if (fp != null) { + favoriteGroups.get(p.getCategory()).remove(fp); + cachedFavoritePoints.remove(fp); + fp.setStored(false); + } + backupSilently(); + } finally{ + db.close(); + } + return true; + } + return false; + } + + public boolean deleteGroup(String group){ + checkFavoritePoints(); + FavouritePoint fp = new FavouritePoint(0, 0, "", group); + if(deleteFavourite(fp)){ + favoriteGroups.remove(group); + backupSilently(); + } + return false; + } + + public boolean addFavourite(FavouritePoint p) { + checkFavoritePoints(); + if(p.getName().equals("") && favoriteGroups.containsKey(p.getCategory())){ + return true; + } + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + db.execSQL( + "INSERT INTO " + FAVOURITE_TABLE_NAME + " (" + FAVOURITE_COL_NAME + ", " + FAVOURITE_COL_CATEGORY + ", " + + FAVOURITE_COL_LAT + ", " + FAVOURITE_COL_LON + ")" + " VALUES (?, ?, ?, ?)", new Object[] { p.getName(), p.getCategory(), p.getLatitude(), p.getLongitude() }); //$NON-NLS-1$ //$NON-NLS-2$ + if (!favoriteGroups.containsKey(p.getCategory())) { + favoriteGroups.put(p.getCategory(), new ArrayList()); + if (!p.getName().equals("")) { + addFavourite(new FavouritePoint(0, 0, "", p.getCategory())); + } + } + if (!p.getName().equals("")) { + favoriteGroups.get(p.getCategory()).add(p); + cachedFavoritePoints.add(p); + } + p.setStored(true); + backupSilently(); + } finally { + db.close(); + } + return true; + } + return false; + } + + private void addCategoryQuery(String category, SQLiteConnection db) { + db.execSQL("INSERT INTO " + FAVOURITE_TABLE_NAME + + " (" +FAVOURITE_COL_NAME +", " +FAVOURITE_COL_CATEGORY +", " +FAVOURITE_COL_LAT +", " +FAVOURITE_COL_LON + ")" + + " VALUES (?, ?, ?, ?)", new Object[] { "", category, 0f, 0f }); //$NON-NLS-1$ //$NON-NLS-2$ + } + + + private void recalculateCachedFavPoints(){ + ArrayList temp = new ArrayList(); + for(List f : favoriteGroups.values()){ + temp.addAll(f); + } + cachedFavoritePoints = temp; + } + + private void checkFavoritePoints(){ + if(favoriteGroups == null){ + favoriteGroups = new TreeMap>(Collator.getInstance()); + SQLiteConnection db = openConnection(true); + if (db != null) { + try { + SQLiteCursor query = db.rawQuery("SELECT " + FAVOURITE_COL_NAME + ", " + FAVOURITE_COL_CATEGORY + ", " + FAVOURITE_COL_LAT + "," + FAVOURITE_COL_LON + " FROM " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + FAVOURITE_TABLE_NAME, null); + cachedFavoritePoints.clear(); + if (query.moveToFirst()) { + do { + String name = query.getString(0); + String cat = query.getString(1); + if(!favoriteGroups.containsKey(cat)){ + favoriteGroups.put(cat, new ArrayList()); + } + if (!name.equals("")) { + FavouritePoint p = new FavouritePoint(); + p.setName(name); + p.setCategory(cat); + p.setStored(true); + p.setLatitude(query.getDouble(2)); + p.setLongitude(query.getDouble(3)); + favoriteGroups.get(cat).add(p); + } + } while (query.moveToNext()); + } + query.close(); + } finally { + db.close(); + } + } + recalculateCachedFavPoints(); + } + } + + + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/GPXUtilities.java b/OsmAnd-java/src/net/osmand/plus/GPXUtilities.java new file mode 100644 index 0000000000..7779ac6239 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/GPXUtilities.java @@ -0,0 +1,566 @@ +package net.osmand.plus; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Stack; +import java.util.TimeZone; + +import net.osmand.Location; +import net.osmand.PlatformUtil; +import net.osmand.plus.GPXUtilities.GPXFile; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + + +public class GPXUtilities { + public final static Log log = PlatformUtil.getLog(GPXUtilities.class); + + private final static String GPX_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$ + + private final static NumberFormat latLonFormat = new DecimalFormat("0.00#####", new DecimalFormatSymbols(new Locale("EN", "US"))); + + public static class GPXExtensions { + Map extensions = null; + + public Map getExtensionsToRead() { + if(extensions == null){ + return Collections.emptyMap(); + } + return extensions; + } + + public Map getExtensionsToWrite() { + if(extensions == null){ + extensions = new LinkedHashMap(); + } + return extensions; + } + + } + + public static class WptPt extends GPXExtensions { + public double lat; + public double lon; + public String name = null; + public String category = null; + public String desc = null; + // by default + public long time = 0; + public double ele = Double.NaN; + public double speed = 0; + public double hdop = Double.NaN; + + public WptPt() {}; + + public WptPt(double lat, double lon, long time, double ele, double speed, double hdop) { + this.lat = lat; + this.lon = lon; + this.time = time; + this.ele = ele; + this.speed = speed; + this.hdop = hdop; + } + + } + + public static class TrkSegment extends GPXExtensions { + public List points = new ArrayList(); + + } + + public static class Track extends GPXExtensions { + public String name = null; + public String desc = null; + public List segments = new ArrayList(); + + } + + public static class Route extends GPXExtensions { + public String name = null; + public String desc = null; + public List points = new ArrayList(); + + } + + public static class GPXFile extends GPXExtensions { + public String author; + public List tracks = new ArrayList(); + public List points = new ArrayList(); + public List routes = new ArrayList(); + public String warning = null; + public String path = ""; + public boolean showCurrentTrack; + + public List> processedPointsToDisplay = new ArrayList>(); + + public boolean isCloudmadeRouteFile(){ + return "cloudmade".equalsIgnoreCase(author); + } + + public void proccessPoints(){ + List> tpoints = new ArrayList>(); + boolean created = false; + for (Track t : tracks) { + for (TrkSegment ts : t.segments) { + if(ts.points.size() > 0) { + created = true; + tpoints.add(ts.points); + } + } + } + if(!created && routes.size() > 0) { + for(Route r : routes) { + tpoints.add(r.points); + } + } + processedPointsToDisplay = tpoints; + } + + public WptPt findPointToShow(){ + for(Track t : tracks){ + for(TrkSegment s : t.segments){ + if(s.points.size() > 0){ + return s.points.get(0); + } + } + } + for (Route s : routes) { + if (s.points.size() > 0) { + return s.points.get(0); + } + } + if (points.size() > 0) { + return points.get(0); + } + return null; + } + + public boolean isEmpty() { + for (Track t : tracks) { + if (t.segments != null) { + for (TrkSegment s : t.segments) { + boolean tracksEmpty = s.points.isEmpty(); + if (!tracksEmpty) { + return false; + } + } + } + } + return points.isEmpty() && routes.isEmpty(); + } + + + } + + + public static String writeGpxFile(File fout, GPXFile file, ClientContext ctx) { + try { + SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + FileOutputStream output = new FileOutputStream(fout); + XmlSerializer serializer = ctx.getInternalAPI().newSerializer(); + serializer.setOutput(output, "UTF-8"); //$NON-NLS-1$ + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); //$NON-NLS-1$ + serializer.startDocument("UTF-8", true); //$NON-NLS-1$ + serializer.startTag(null, "gpx"); //$NON-NLS-1$ + serializer.attribute(null, "version", "1.1"); //$NON-NLS-1$ //$NON-NLS-2$ + if(file.author == null ){ + serializer.attribute(null, "creator", Version.getAppName(ctx)); //$NON-NLS-1$ + } else { + serializer.attribute(null, "creator", file.author); //$NON-NLS-1$ + } + serializer.attribute(null, "xmlns", "http://www.topografix.com/GPX/1/1"); //$NON-NLS-1$ //$NON-NLS-2$ + serializer.attribute(null, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + serializer.attribute(null, "xsi:schemaLocation", "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"); + + + for (Track track : file.tracks) { + serializer.startTag(null, "trk"); //$NON-NLS-1$ + writeNotNullText(serializer, "name", track.name); + writeNotNullText(serializer, "desc", track.desc); + for (TrkSegment segment : track.segments) { + serializer.startTag(null, "trkseg"); //$NON-NLS-1$ + for (WptPt p : segment.points) { + serializer.startTag(null, "trkpt"); //$NON-NLS-1$ + writeWpt(format, serializer, p); + serializer.endTag(null, "trkpt"); //$NON-NLS-1$ + } + serializer.endTag(null, "trkseg"); //$NON-NLS-1$ + } + writeExtensions(serializer, track); + serializer.endTag(null, "trk"); //$NON-NLS-1$ + } + + for (Route track : file.routes) { + serializer.startTag(null, "rte"); //$NON-NLS-1$ + writeNotNullText(serializer, "name", track.name); + writeNotNullText(serializer, "desc", track.desc); + + for (WptPt p : track.points) { + serializer.startTag(null, "rtept"); //$NON-NLS-1$ + writeWpt(format, serializer, p); + serializer.endTag(null, "rtept"); //$NON-NLS-1$ + } + writeExtensions(serializer, track); + serializer.endTag(null, "rte"); //$NON-NLS-1$ + } + + for (WptPt l : file.points) { + serializer.startTag(null, "wpt"); //$NON-NLS-1$ + writeWpt(format, serializer, l); + serializer.endTag(null, "wpt"); //$NON-NLS-1$ + } + + serializer.endTag(null, "gpx"); //$NON-NLS-1$ + serializer.flush(); + serializer.endDocument(); + } catch (RuntimeException e) { + log.error("Error saving gpx", e); //$NON-NLS-1$ + return ctx.getString(R.string.error_occurred_saving_gpx); + } catch (IOException e) { + log.error("Error saving gpx", e); //$NON-NLS-1$ + return ctx.getString(R.string.error_occurred_saving_gpx); + } + return null; + } + + private static void writeNotNullText(XmlSerializer serializer, String tag, String value) throws IOException { + if(value != null){ + serializer.startTag(null, tag); + serializer.text(value); + serializer.endTag(null, tag); + } + } + + private static void writeExtensions(XmlSerializer serializer, GPXExtensions p) throws IOException { + if (!p.getExtensionsToRead().isEmpty()) { + serializer.startTag(null, "extensions"); + for (Map.Entry s : p.getExtensionsToRead().entrySet()) { + writeNotNullText(serializer, s.getKey(), s.getValue()); + } + serializer.endTag(null, "extensions"); + } + } + + private static void writeWpt(SimpleDateFormat format, XmlSerializer serializer, WptPt p) throws IOException { + serializer.attribute(null, "lat", latLonFormat.format(p.lat)); //$NON-NLS-1$ //$NON-NLS-2$ + serializer.attribute(null, "lon", latLonFormat.format(p.lon)); //$NON-NLS-1$ //$NON-NLS-2$ + + if(!Double.isNaN(p.ele)){ + writeNotNullText(serializer, "ele", p.ele+""); + } + writeNotNullText(serializer, "name", p.name); + writeNotNullText(serializer, "category", p.category); + writeNotNullText(serializer, "desc", p.desc); + if(!Double.isNaN(p.hdop)){ + writeNotNullText(serializer, "hdop", p.hdop+""); + } + if(p.time != 0){ + writeNotNullText(serializer, "time", format.format(new Date(p.time))); + } + if (p.speed > 0) { + p.getExtensionsToWrite().put("speed", p.speed+""); + } + writeExtensions(serializer, p); + } + + + public static class GPXFileResult { + public ArrayList> locations = new ArrayList>(); + public ArrayList wayPoints = new ArrayList(); + // special case for cloudmate gpx : they discourage common schema + // by using waypoint as track points and rtept are not very close to real way + // such as wpt. However they provide additional information into gpx. + public boolean cloudMadeFile; + public String error; + + public Location findFistLocation(){ + for(List l : locations){ + for(Location ls : l){ + if(ls != null){ + return ls; + } + } + } + return null; + } + } + + + private static String readText(XmlPullParser parser, String key) throws XmlPullParserException, IOException { + int tok; + String text = null; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if(tok == XmlPullParser.END_TAG && parser.getName().equals(key)){ + break; + } else if(tok == XmlPullParser.TEXT){ + if(text == null){ + text = parser.getText(); + } else { + text += parser.getText(); + } + } + + } + return text; + } + + public static GPXFile loadGPXFile(ClientContext ctx, File f, boolean convertCloudmadeSource) { + try { + GPXFile file = loadGPXFile(ctx, new FileInputStream(f), convertCloudmadeSource); + file.path = f.getAbsolutePath(); + return file; + } catch (FileNotFoundException e) { + GPXFile res = new GPXFile(); + res.path = f.getAbsolutePath(); + log.error("Error reading gpx", e); //$NON-NLS-1$ + res.warning = ctx.getString(R.string.error_reading_gpx); + return res; + } + } + + public static GPXFile loadGPXFile(ClientContext ctx, InputStream f, boolean convertCloudmadeSource) { + GPXFile res = new GPXFile(); + SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + XmlPullParser parser = ctx.getInternalAPI().newPullParser(); + parser.setInput(getUTF8Reader(f)); //$NON-NLS-1$ + Stack parserState = new Stack(); + boolean extensionReadMode = false; + parserState.push(res); + int tok; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + Object parse = parserState.peek(); + String tag = parser.getName(); + if (extensionReadMode && parse instanceof GPXExtensions) { + String value = readText(parser, tag); + if (value != null) { + ((GPXExtensions) parse).getExtensionsToWrite().put(tag, value); + if (tag.equals("speed") && parse instanceof WptPt) { + try { + ((WptPt) parse).speed = Float.parseFloat(value); + } catch (NumberFormatException e) { + } + } + } + + } else if (parse instanceof GPXExtensions && tag.equals("extensions")) { + extensionReadMode = true; + } else { + if (parse instanceof GPXFile) { + if (parser.getName().equals("gpx")) { + ((GPXFile) parse).author = parser.getAttributeValue("", "creator"); + } + if (parser.getName().equals("trk")) { + Track track = new Track(); + ((GPXFile) parse).tracks.add(track); + parserState.push(track); + } + if (parser.getName().equals("rte")) { + Route route = new Route(); + ((GPXFile) parse).routes.add(route); + parserState.push(route); + } + if (parser.getName().equals("wpt")) { + WptPt wptPt = parseWptAttributes(parser); + ((GPXFile) parse).points.add(wptPt); + parserState.push(wptPt); + } + } else if (parse instanceof Route) { + if (parser.getName().equals("name")) { + ((Route) parse).name = readText(parser, "name"); + } + if (parser.getName().equals("desc")) { + ((Route) parse).desc = readText(parser, "desc"); + } + if (parser.getName().equals("rtept")) { + WptPt wptPt = parseWptAttributes(parser); + ((Route) parse).points.add(wptPt); + parserState.push(wptPt); + } + } else if (parse instanceof Track) { + if (parser.getName().equals("name")) { + ((Track) parse).name = readText(parser, "name"); + } + if (parser.getName().equals("desc")) { + ((Track) parse).desc = readText(parser, "desc"); + } + if (parser.getName().equals("trkseg")) { + TrkSegment trkSeg = new TrkSegment(); + ((Track) parse).segments.add(trkSeg); + parserState.push(trkSeg); + } + } else if (parse instanceof TrkSegment) { + if (parser.getName().equals("trkpt")) { + WptPt wptPt = parseWptAttributes(parser); + ((TrkSegment) parse).points.add(wptPt); + parserState.push(wptPt); + } + // main object to parse + } else if (parse instanceof WptPt) { + if (parser.getName().equals("name")) { + ((WptPt) parse).name = readText(parser, "name"); + } else if (parser.getName().equals("desc")) { + ((WptPt) parse).desc = readText(parser, "desc"); + } else if (tag.equals("category")) { + ((WptPt) parse).category = readText(parser, "category"); + } else if (parser.getName().equals("ele")) { + String text = readText(parser, "ele"); + if (text != null) { + try { + ((WptPt) parse).ele = Float.parseFloat(text); + } catch (NumberFormatException e) { + } + } + } else if (parser.getName().equals("hdop")) { + String text = readText(parser, "hdop"); + if (text != null) { + try { + ((WptPt) parse).hdop = Float.parseFloat(text); + } catch (NumberFormatException e) { + } + } + } else if (parser.getName().equals("time")) { + String text = readText(parser, "time"); + if (text != null) { + try { + ((WptPt) parse).time = format.parse(text).getTime(); + } catch (ParseException e) { + } + } + } + } + } + + } else if (tok == XmlPullParser.END_TAG) { + Object parse = parserState.peek(); + String tag = parser.getName(); + if (parse instanceof GPXExtensions && tag.equals("extensions")) { + extensionReadMode = false; + } + + if(tag.equals("trkpt")){ + Object pop = parserState.pop(); + assert pop instanceof WptPt; + } else if(tag.equals("wpt")){ + Object pop = parserState.pop(); + assert pop instanceof WptPt; + } else if(tag.equals("rtept")){ + Object pop = parserState.pop(); + assert pop instanceof WptPt; + } else if(tag.equals("trk")){ + Object pop = parserState.pop(); + assert pop instanceof Track; + } else if(tag.equals("rte")){ + Object pop = parserState.pop(); + assert pop instanceof Route; + } else if(tag.equals("trkseg")){ + Object pop = parserState.pop(); + assert pop instanceof TrkSegment; + } + } + } + if(convertCloudmadeSource && res.isCloudmadeRouteFile()){ + Track tk = new Track(); + res.tracks.add(tk); + TrkSegment segment = new TrkSegment(); + tk.segments.add(segment); + + for(WptPt wp : res.points){ + segment.points.add(wp); + } + res.points.clear(); + } + } catch (RuntimeException e) { + log.error("Error reading gpx", e); //$NON-NLS-1$ + res.warning = ctx.getString(R.string.error_reading_gpx) + " " + e.getMessage(); + } catch (XmlPullParserException e) { + log.error("Error reading gpx", e); //$NON-NLS-1$ + res.warning = ctx.getString(R.string.error_reading_gpx) + " " + e.getMessage(); + } catch (IOException e) { + log.error("Error reading gpx", e); //$NON-NLS-1$ + res.warning = ctx.getString(R.string.error_reading_gpx) + " " + e.getMessage(); + } + + return res; + } + + private static Reader getUTF8Reader(InputStream f) throws IOException { + BufferedInputStream bis = new BufferedInputStream(f); + assert bis.markSupported(); + bis.mark(3); + boolean reset = true; + byte[] t = new byte[3]; + bis.read(t); + if (t[0] == ((byte)0xef) && t[1]== ((byte)0xbb) && t[2] == ((byte)0xbf)) { + reset = false; + } + if(reset) { + bis.reset(); + } + return new InputStreamReader(bis, "UTF-8"); + } + + + + private static WptPt parseWptAttributes(XmlPullParser parser) { + WptPt wpt = new WptPt(); + try { + wpt.lat = Double.parseDouble(parser.getAttributeValue("", "lat")); //$NON-NLS-1$ //$NON-NLS-2$ + wpt.lon = Double.parseDouble(parser.getAttributeValue("", "lon")); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (NumberFormatException e) { + } + return wpt; + } + + public static void mergeGPXFileInto(GPXFile to, GPXFile from) { + if(from == null) { + return; + } + if(from.showCurrentTrack) { + to.showCurrentTrack = true; + } + if(from.points != null) { + to.points.addAll(from.points); + } + if(from.tracks != null) { + to.tracks.addAll(from.tracks); + } + if(from.routes != null) { + to.routes.addAll(from.routes); + } + if(from.warning != null) { + to.warning = from.warning; + } + + } + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/NameFinderPoiFilter.java b/OsmAnd-java/src/net/osmand/plus/NameFinderPoiFilter.java new file mode 100644 index 0000000000..8e3c65b98d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/NameFinderPoiFilter.java @@ -0,0 +1,142 @@ +package net.osmand.plus; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +import net.osmand.PlatformUtil; +import net.osmand.ResultMatcher; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.util.MapUtils; +import net.sf.junidecode.Junidecode; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + + +public class NameFinderPoiFilter extends PoiFilter { + + public static final String FILTER_ID = "name_finder"; //$NON-NLS-1$ + private static final Log log = PlatformUtil.getLog(NameFinderPoiFilter.class); + private static final int LIMIT = 300; + + List searchedAmenities = new ArrayList(); + + + private String query = ""; //$NON-NLS-1$ + private String lastError = ""; //$NON-NLS-1$ + + public NameFinderPoiFilter(ClientContext application) { + super(null, application); + this.name = application.getString(R.string.poi_filter_nominatim); //$NON-NLS-1$ + this.distanceToSearchValues = new double[] {1, 2, 5, 10, 20, 30, 100, 250 }; + this.filterId = FILTER_ID; + } + + @Override + public List searchAgain(double lat, double lon) { + MapUtils.sortListOfMapObject(searchedAmenities, lat, lon); + return searchedAmenities; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + @Override + protected List searchAmenities(double lat, double lon, double topLatitude, + double bottomLatitude, double leftLongitude, double rightLongitude, ResultMatcher matcher) { + searchedAmenities.clear(); + + String viewbox = "viewboxlbrt="+((float) leftLongitude)+","+((float) bottomLatitude)+","+((float) rightLongitude)+","+((float) topLatitude); + try { + lastError = ""; + String urlq = "http://nominatim.openstreetmap.org/search/"+URLEncoder.encode(query)+ "?format=xml&addressdetails=1&limit="+LIMIT+"&bounded=1&"+viewbox; + log.info(urlq); + URL url = new URL(urlq); //$NON-NLS-1$ + InputStream stream = url.openStream(); + XmlPullParser parser = application.getInternalAPI().newPullParser(); + parser.setInput(stream, "UTF-8"); //$NON-NLS-1$ + int eventType; + int namedDepth= 0; + Amenity a = null; + while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("searchresults")) { //$NON-NLS-1$ + String err = parser.getAttributeValue("", "error"); //$NON-NLS-1$ //$NON-NLS-2$ + if (err != null && err.length() > 0) { + lastError = err; + stream.close(); + return searchedAmenities; + } + } + if (parser.getName().equals("place")) { //$NON-NLS-1$ + namedDepth++; + if (namedDepth == 1) { + try { + a = new Amenity(); + a.setLocation(Double.parseDouble(parser.getAttributeValue("", "lat")), //$NON-NLS-1$//$NON-NLS-2$ + Double.parseDouble(parser.getAttributeValue("", "lon"))); //$NON-NLS-1$//$NON-NLS-2$ + a.setId(Long.parseLong(parser.getAttributeValue("", "place_id"))); //$NON-NLS-1$ //$NON-NLS-2$ + String name = parser.getAttributeValue("", "display_name"); //$NON-NLS-1$//$NON-NLS-2$ + a.setName(name); + a.setEnName(Junidecode.unidecode(name)); + a.setType(AmenityType.OTHER); + a.setSubType(parser.getAttributeValue("", "type")); //$NON-NLS-1$//$NON-NLS-2$ + if (matcher == null || matcher.publish(a)) { + searchedAmenities.add(a); + } + } catch (NumberFormatException e) { + log.info("Invalid attributes", e); //$NON-NLS-1$ + } + } + } else if (a != null && parser.getName().equals(a.getSubType())) { + if (parser.next() == XmlPullParser.TEXT) { + String name = parser.getText(); + if (name != null) { + a.setName(name); + a.setEnName(Junidecode.unidecode(name)); + } + } + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("place")) { //$NON-NLS-1$ + namedDepth--; + if(namedDepth == 0){ + a = null; + } + } + } + } + stream.close(); + } catch (IOException e) { + log.error("Error loading name finder poi", e); //$NON-NLS-1$ + lastError = getApplication().getString(R.string.input_output_error); //$NON-NLS-1$ + } catch (XmlPullParserException e) { + log.error("Error parsing name finder poi", e); //$NON-NLS-1$ + lastError = getApplication().getString(R.string.input_output_error); //$NON-NLS-1$ + } + MapUtils.sortListOfMapObject(searchedAmenities, lat, lon); + return searchedAmenities; + } + + public String getLastError() { + return lastError; + } + + public List getSearchedAmenities() { + return searchedAmenities; + } + + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/OsmAndFormatter.java b/OsmAnd-java/src/net/osmand/plus/OsmAndFormatter.java new file mode 100644 index 0000000000..4624d01bdb --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/OsmAndFormatter.java @@ -0,0 +1,203 @@ +package net.osmand.plus; + +import java.text.MessageFormat; + +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.data.City.CityType; +import net.osmand.plus.OsmandSettings.MetricsConstants; + +public class OsmAndFormatter { + private final static float METERS_IN_KILOMETER = 1000f; + private final static float METERS_IN_ONE_MILE = 1609.344f; // 1609.344 + private final static float YARDS_IN_ONE_METER = 1.0936f; + private final static float FOOTS_IN_ONE_METER = YARDS_IN_ONE_METER * 3f; + + public static double calculateRoundedDist(double distInMeters, ClientContext ctx) { + OsmandSettings settings = ctx.getSettings(); + MetricsConstants mc = settings.METRIC_SYSTEM.get(); + double mainUnitInMeter = 1; + double metersInSecondUnit = METERS_IN_KILOMETER; + if (mc == MetricsConstants.MILES_AND_FOOTS) { + mainUnitInMeter = FOOTS_IN_ONE_METER; + metersInSecondUnit = METERS_IN_ONE_MILE; + } else if(mc == MetricsConstants.MILES_AND_YARDS){ + mainUnitInMeter = YARDS_IN_ONE_METER; + metersInSecondUnit = METERS_IN_ONE_MILE ; + } + // 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 ... + + int generator = 1; + byte pointer = 1; + double point = mainUnitInMeter; + while(distInMeters * point > generator){ + if (pointer++ % 3 == 2) { + generator = generator * 5 / 2; + } else { + generator *= 2; + } + if(point == mainUnitInMeter && metersInSecondUnit * mainUnitInMeter * 0.9f <= generator ){ + point = 1 / metersInSecondUnit; + generator = 1; + pointer = 1; + } + } + + return (generator / point); + } + + public static String getFormattedDistance(float meters, ClientContext ctx) { + OsmandSettings settings = ctx.getSettings(); + MetricsConstants mc = settings.METRIC_SYSTEM.get(); + int mainUnitStr; + float mainUnitInMeters; + if (mc == MetricsConstants.KILOMETERS_AND_METERS) { + mainUnitStr = R.string.km; + mainUnitInMeters = METERS_IN_KILOMETER; + } else { + mainUnitStr = R.string.mile; + mainUnitInMeters = METERS_IN_ONE_MILE; + } + + if (meters >= 100 * mainUnitInMeters) { + return (int) (meters / mainUnitInMeters) + " " + ctx.getString(mainUnitStr); //$NON-NLS-1$ + } else if (meters > 9.99f * mainUnitInMeters) { + return MessageFormat.format("{0,number,#.#} " + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters); //$NON-NLS-1$ + } else if (meters > 0.999f * mainUnitInMeters) { + return MessageFormat.format("{0,number,#.##} " + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters); //$NON-NLS-1$ + } else { + if (mc == MetricsConstants.KILOMETERS_AND_METERS) { + return ((int) meters) + " " + ctx.getString(R.string.m); //$NON-NLS-1$ + } else if (mc == MetricsConstants.MILES_AND_FOOTS) { + int foots = (int) (meters * FOOTS_IN_ONE_METER); + return foots + " " + ctx.getString(R.string.foot); //$NON-NLS-1$ + } else if (mc == MetricsConstants.MILES_AND_YARDS) { + int yards = (int) (meters * YARDS_IN_ONE_METER); + return yards + " " + ctx.getString(R.string.yard); //$NON-NLS-1$ + } + return ((int) meters) + " " + ctx.getString(R.string.m); //$NON-NLS-1$ + } + } + + public static String getFormattedAlt(double alt, ClientContext ctx) { + OsmandSettings settings = ctx.getSettings(); + MetricsConstants mc = settings.METRIC_SYSTEM.get(); + if (mc == MetricsConstants.KILOMETERS_AND_METERS) { + return ((int) alt) + " " + ctx.getString(R.string.m); + } else { + return ((int) (alt * FOOTS_IN_ONE_METER)) + " " + ctx.getString(R.string.foot); + } + } + + public static String getFormattedSpeed(float metersperseconds, ClientContext ctx) { + OsmandSettings settings = ctx.getSettings(); + MetricsConstants mc = settings.METRIC_SYSTEM.get(); + ApplicationMode am = settings.getApplicationMode(); + float kmh = metersperseconds * 3.6f; + if (mc == MetricsConstants.KILOMETERS_AND_METERS) { + if (kmh >= 10 || (am == ApplicationMode.CAR)) { + return ((int) Math.round(kmh)) + " " + ctx.getString(R.string.km_h); + } + int kmh10 = (int) (kmh * 10f); + // calculate 2.0 km/h instead of 2 km/h in order to not stress UI text lengh + return (kmh10 / 10f) + " " + ctx.getString(R.string.km_h); + } else { + float mph = kmh * METERS_IN_KILOMETER / METERS_IN_ONE_MILE; + if (mph >= 10) { + return ((int) Math.round(mph)) + " " + ctx.getString(R.string.mile_per_hour); + } else { + int mph10 = (int) (mph * 10f); + return (mph10 / 10f) + " " + ctx.getString(R.string.mile_per_hour); + } + } + } + + + public static String toPublicString(CityType t, ClientContext ctx) { + switch (t) { + case CITY: + return ctx.getString(R.string.city_type_city); + case HAMLET: + return ctx.getString(R.string.city_type_hamlet); + case TOWN: + return ctx.getString(R.string.city_type_town); + case VILLAGE: + return ctx.getString(R.string.city_type_village); + case SUBURB: + return ctx.getString(R.string.city_type_suburb); + } + return ""; + } + public static String toPublicString(AmenityType t, ClientContext ctx) { + switch (t) { + case SUSTENANCE: + return ctx.getString(R.string.amenity_type_sustenance); + case EDUCATION: + return ctx.getString(R.string.amenity_type_education); + case TRANSPORTATION: + return ctx.getString(R.string.amenity_type_transportation); + case FINANCE: + return ctx.getString(R.string.amenity_type_finance); + case HEALTHCARE: + return ctx.getString(R.string.amenity_type_healthcare); + case ENTERTAINMENT: + return ctx.getString(R.string.amenity_type_entertainment); + case TOURISM: + return ctx.getString(R.string.amenity_type_tourism); + case HISTORIC: + return ctx.getString(R.string.amenity_type_historic); + case NATURAL: + return ctx.getString(R.string.amenity_type_natural); + case USER_DEFINED: + return ctx.getString(R.string.amenity_type_user_defined); + case OSMWIKI : + return ctx.getString(R.string.amenity_type_wikiosm); + case SHOP: + return ctx.getString(R.string.amenity_type_shop); + case LEISURE: + return ctx.getString(R.string.amenity_type_leisure); + case SPORT: + return ctx.getString(R.string.amenity_type_sport); + case BARRIER: + return ctx.getString(R.string.amenity_type_barrier); + case LANDUSE: + return ctx.getString(R.string.amenity_type_landuse); + case MAN_MADE: + return ctx.getString(R.string.amenity_type_manmade); + case OFFICE: + return ctx.getString(R.string.amenity_type_office); + case EMERGENCY: + return ctx.getString(R.string.amenity_type_emergency); + case MILITARY: + return ctx.getString(R.string.amenity_type_military); + case ADMINISTRATIVE: + return ctx.getString(R.string.amenity_type_administrative); + case GEOCACHE: + return ctx.getString(R.string.amenity_type_geocache); + case OTHER: + return ctx.getString(R.string.amenity_type_other); + } + return ""; + } + + + public static String getPoiSimpleFormat(Amenity amenity, ClientContext ctx, boolean en){ + return toPublicString(amenity.getType(), ctx) + " : " + getPoiStringWithoutType(amenity, en); //$NON-NLS-1$ + } + + public static String getPoiStringWithoutType(Amenity amenity, boolean en) { + String type = SpecialPhrases.getSpecialPhrase(amenity.getSubType()); + String n = amenity.getName(en); + if (n.indexOf(type) != -1) { + // type is contained in name e.g. + // n = "Bakery the Corner" + // type = "Bakery" + // no need to repeat this + return n; + } + if (n.length() == 0) { + return type; + } + return type + " " + n; //$NON-NLS-1$ + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/OsmandSettings.java b/OsmAnd-java/src/net/osmand/plus/OsmandSettings.java new file mode 100644 index 0000000000..3a77a358e7 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/OsmandSettings.java @@ -0,0 +1,1492 @@ +package net.osmand.plus; + + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import net.osmand.IndexConstants; +import net.osmand.StateChangedListener; +import net.osmand.data.LatLon; +import net.osmand.map.ITileSource; +import net.osmand.map.TileSourceManager; +import net.osmand.map.TileSourceManager.TileSourceTemplate; +import net.osmand.plus.access.AccessibilityMode; +import net.osmand.plus.access.RelativeDirectionStyle; +import net.osmand.plus.api.SettingsAPI; +import net.osmand.plus.api.SettingsAPI.SettingsEditor; +import net.osmand.plus.render.RendererRegistry; +import net.osmand.plus.routing.RouteProvider.RouteService; +import net.osmand.render.RenderingRulesStorage; + +public class OsmandSettings { + + public interface OsmandPreference { + T get(); + + boolean set(T obj); + + boolean setModeValue(ApplicationMode m, T obj); + + T getModeValue(ApplicationMode m); + + String getId(); + + void resetToDefault(); + + void overrideDefaultValue(T newDefaultValue); + + void addListener(StateChangedListener listener); + + void removeListener(StateChangedListener listener); + } + + private abstract class PreferenceWithListener implements OsmandPreference { + private List> l = null; + + @Override + public void addListener(StateChangedListener listener) { + if(l == null) { + l = new LinkedList>(); + } + if(!l.contains(listener)) { + l.add(listener); + } + } + + public void fireEvent(T value){ + if (l != null) { + for (StateChangedListener t : l) { + t.stateChanged(value); + } + } + } + + @Override + public void removeListener(StateChangedListener listener) { + if(l != null) { + l.remove(listener); + } + } + } + + // These settings are stored in SharedPreferences + private static final String SHARED_PREFERENCES_NAME = "net.osmand.settings"; //$NON-NLS-1$ + + /// Settings variables + private final ClientContext ctx; + private SettingsAPI settingsAPI; + private Object globalPreferences; + private Object defaultProfilePreferences; + private Object profilePreferences; + private ApplicationMode currentMode; + private Map> registeredPreferences = + new LinkedHashMap>(); + + // cache variables + private long lastTimeInternetConnectionChecked = 0; + private boolean internetConnectionAvailable = true; + private List internetAvailableSourceTemplates = null; + + + + protected OsmandSettings(ClientContext clientContext) { + ctx = clientContext; + settingsAPI = ctx.getSettingsAPI(); + + globalPreferences = settingsAPI.getPreferenceObject(SHARED_PREFERENCES_NAME); + // start from default settings + currentMode = ApplicationMode.DEFAULT; + + defaultProfilePreferences = getProfilePreferences(ApplicationMode.DEFAULT); + profilePreferences = defaultProfilePreferences; + currentMode = readApplicationMode(); + profilePreferences = getProfilePreferences(currentMode); + } + + public ClientContext getContext() { + return ctx; + } + + public static String getSharedPreferencesName(ApplicationMode mode){ + if(mode == null){ + return SHARED_PREFERENCES_NAME; + } else { + return SHARED_PREFERENCES_NAME + "." + mode.name().toLowerCase(); + } + } + + public Object getProfilePreferences(ApplicationMode mode){ + return settingsAPI.getPreferenceObject(getSharedPreferencesName(mode)); + } + + public Object getGlobalPreferences(){ + return settingsAPI.getPreferenceObject(getSharedPreferencesName(null)); + } + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference APPLICATION_MODE = new PreferenceWithListener(){ + @Override + public String getId() { + return "application_mode"; + }; + + @Override + public ApplicationMode get() { + return currentMode; + } + + @Override + public void overrideDefaultValue(ApplicationMode newDefaultValue) { + throw new UnsupportedOperationException(); + } + + @Override + public void resetToDefault() { + set(ApplicationMode.DEFAULT); + }; + + @Override + public boolean set(ApplicationMode val) { + ApplicationMode oldMode = currentMode; + boolean changed = settingsAPI.edit(globalPreferences).putString(getId(), val.name()).commit(); + if(changed){ + currentMode = val; + profilePreferences = getProfilePreferences(currentMode); + fireEvent(oldMode); + } + return changed; + } + + @Override + public ApplicationMode getModeValue(ApplicationMode m) { + return m; + } + + @Override + public boolean setModeValue(ApplicationMode m, ApplicationMode obj) { + throw new UnsupportedOperationException(); + } + }; + + public ApplicationMode getApplicationMode(){ + return APPLICATION_MODE.get(); + } + + protected ApplicationMode readApplicationMode() { + String s = settingsAPI.getString(globalPreferences, APPLICATION_MODE.getId(), ApplicationMode.DEFAULT.name()); + try { + return ApplicationMode.valueOf(s); + } catch (IllegalArgumentException e) { + return ApplicationMode.DEFAULT; + } + } + + + // Check internet connection available every 15 seconds + public boolean isInternetConnectionAvailable(){ + return isInternetConnectionAvailable(false); + } + public boolean isInternetConnectionAvailable(boolean update){ + long delta = System.currentTimeMillis() - lastTimeInternetConnectionChecked; + if(delta < 0 || delta > 15000 || update){ + internetConnectionAvailable = ctx.getExternalServiceAPI().isInternetConnected(); + } + return internetConnectionAvailable; + } + + + /////////////// PREFERENCES classes //////////////// + + public abstract class CommonPreference extends PreferenceWithListener { + private final String id; + private boolean global; + private T cachedValue; + private Object cachedPreference; + private boolean cache; + private Map defaultValues; + private T defaultValue; + + + public CommonPreference(String id, T defaultValue){ + this.id = id; + this.defaultValue = defaultValue; + } + + public CommonPreference makeGlobal(){ + global = true; + return this; + } + + public CommonPreference cache(){ + cache = true; + return this; + } + + public CommonPreference makeProfile(){ + global = false; + return this; + } + + protected Object getPreferences(){ + return global ? globalPreferences : profilePreferences; + } + + public void setModeDefaultValue(ApplicationMode mode, T defValue){ + if(defaultValues == null){ + defaultValues = new LinkedHashMap(); + } + defaultValues.put(mode, defValue); + } + + @Override + public boolean setModeValue(ApplicationMode mode, T obj){ + if(global) { + return set(obj); + } + boolean ch = setValue(getProfilePreferences(mode), obj); + fireEvent(obj); + return ch; + } + + public T getProfileDefaultValue(){ + if(global){ + return defaultValue; + } + if(defaultValues != null && defaultValues.containsKey(currentMode)){ + return defaultValues.get(currentMode); + } + return defaultValue; + } + + protected T getDefaultValue(){ + if(global){ + return defaultValue; + } + if(defaultValues != null && defaultValues.containsKey(currentMode)){ + return defaultValues.get(currentMode); + } + if(settingsAPI.contains(defaultProfilePreferences, getId())) { + return getValue(defaultProfilePreferences, defaultValue); + } else { + return defaultValue; + } + } + + @Override + public void overrideDefaultValue(T newDefaultValue) { + this.defaultValue = newDefaultValue; + } + + protected abstract T getValue(Object prefs, T defaultValue); + + protected abstract boolean setValue(Object prefs, T val); + + @Override + public T getModeValue(ApplicationMode mode) { + if(global) { + return get(); + } + T defaultV = defaultValue; + if(defaultValues != null && defaultValues.containsKey(currentMode)){ + defaultV = defaultValues.get(currentMode); + } + return getValue(getProfilePreferences(mode), defaultV); + } + + @Override + public T get() { + if(cache && cachedValue != null && cachedPreference == getPreferences()){ + return cachedValue; + } + cachedPreference = getPreferences(); + cachedValue = getValue(cachedPreference, getDefaultValue()); + return cachedValue; + } + + @Override + public String getId() { + return id; + } + + @Override + public void resetToDefault(){ + set(getDefaultValue()); + } + + @Override + public boolean set(T obj) { + Object prefs = getPreferences(); + if (setValue(prefs, obj)) { + cachedValue = obj; + cachedPreference = prefs; + fireEvent(obj); + return true; + } + return false; + } + + } + + private class BooleanPreference extends CommonPreference { + + + private BooleanPreference(String id, boolean defaultValue) { + super(id, defaultValue); + } + + @Override + protected Boolean getValue(Object prefs, Boolean defaultValue) { + return settingsAPI.getBoolean(prefs, getId(), defaultValue); + } + + @Override + protected boolean setValue(Object prefs, Boolean val) { + return settingsAPI.edit( prefs).putBoolean(getId(), val).commit(); + } + } + + private class BooleanAccessibilityPreference extends BooleanPreference { + + private BooleanAccessibilityPreference(String id, boolean defaultValue) { + super(id, defaultValue); + } + + @Override + protected Boolean getValue(Object prefs, Boolean defaultValue) { + return ctx.getInternalAPI().accessibilityEnabled() ? + super.getValue(prefs, defaultValue) : + defaultValue; + } + + @Override + protected boolean setValue(Object prefs, Boolean val) { + return ctx.getInternalAPI().accessibilityEnabled() ? + super.setValue(prefs, val) : + false; + } + } + + private class IntPreference extends CommonPreference { + + + private IntPreference(String id, int defaultValue) { + super(id, defaultValue); + } + + @Override + protected Integer getValue(Object prefs, Integer defaultValue) { + return settingsAPI.getInt(prefs, getId(), defaultValue); + } + + @Override + protected boolean setValue(Object prefs, Integer val) { + return settingsAPI.edit( prefs).putInt(getId(), val).commit(); + } + + } + + private class LongPreference extends CommonPreference { + + + private LongPreference(String id, long defaultValue) { + super(id, defaultValue); + } + + @Override + protected Long getValue(Object prefs, Long defaultValue) { + return settingsAPI.getLong(prefs, getId(), defaultValue); + } + + @Override + protected boolean setValue(Object prefs, Long val) { + return settingsAPI.edit( prefs).putLong(getId(), val).commit(); + } + + } + + private class FloatPreference extends CommonPreference { + + + private FloatPreference(String id, float defaultValue) { + super(id, defaultValue); + } + + @Override + protected Float getValue(Object prefs, Float defaultValue) { + return settingsAPI.getFloat(prefs,getId(), defaultValue); + } + + @Override + protected boolean setValue(Object prefs, Float val) { + return settingsAPI.edit( prefs).putFloat(getId(), val).commit(); + } + + } + + private class StringPreference extends CommonPreference { + + private StringPreference(String id, String defaultValue) { + super(id, defaultValue); + } + + @Override + protected String getValue(Object prefs, String defaultValue) { + return settingsAPI.getString(prefs, getId(), defaultValue); + } + + @Override + protected boolean setValue(Object prefs, String val) { + return settingsAPI.edit( prefs).putString(getId(), (val != null) ? val.trim() : val).commit(); + } + + } + + private class EnumIntPreference> extends CommonPreference { + + private final E[] values; + + private EnumIntPreference(String id, E defaultValue, E[] values) { + super(id, defaultValue); + this.values = values; + } + + + @Override + protected E getValue(Object prefs, E defaultValue) { + try { + int i = settingsAPI.getInt(prefs, getId(), -1); + if(i >= 0 && i < values.length){ + return values[i]; + } + } catch (ClassCastException ex) { + setValue(prefs, defaultValue); + } + return defaultValue; + } + + @Override + protected boolean setValue(Object prefs,E val) { + return settingsAPI.edit( prefs).putInt(getId(), val.ordinal()).commit(); + } + + } + ///////////// PREFERENCES classes //////////////// + + // this value string is synchronized with settings_pref.xml preference name + private final OsmandPreference ENABLED_PLUGINS = new StringPreference("enabled_plugins", "").makeGlobal(); + + public Set getEnabledPlugins(){ + String plugs = ENABLED_PLUGINS.get(); + StringTokenizer toks = new StringTokenizer(plugs, ","); + Set res = new LinkedHashSet(); + while(toks.hasMoreTokens()) { + res.add(toks.nextToken()); + } + return res; + } + + public void enablePlugin(String pluginId, boolean enable){ + Set set = getEnabledPlugins(); + if(enable){ + set.add(pluginId); + } else { + set.remove(pluginId); + } + StringBuilder serialization = new StringBuilder(); + Iterator it = set.iterator(); + while(it.hasNext()){ + serialization.append(it.next()); + if(it.hasNext()) { + serialization.append(","); + } + } + if(!serialization.toString().equals(ENABLED_PLUGINS.get())) { + ENABLED_PLUGINS.set(serialization.toString()); + } + } + + + @SuppressWarnings("unchecked") + public CommonPreference registerBooleanPreference(String id, boolean defValue) { + if(registeredPreferences.containsKey(id)) { + return (CommonPreference) registeredPreferences.get(id); + } + BooleanPreference p = new BooleanPreference(id, defValue); + registeredPreferences.put(id, p); + return p; + } + + @SuppressWarnings("unchecked") + public CommonPreference registerIntPreference(String id, int defValue) { + if(registeredPreferences.containsKey(id)) { + return (CommonPreference) registeredPreferences.get(id); + } + IntPreference p = new IntPreference(id, defValue); + registeredPreferences.put(id, p); + return p; + } + + @SuppressWarnings("unchecked") + public CommonPreference registerLongPreference(String id, long defValue) { + if(registeredPreferences.containsKey(id)) { + return (CommonPreference) registeredPreferences.get(id); + } + LongPreference p = new LongPreference(id, defValue); + registeredPreferences.put(id, p); + return p; + } + + @SuppressWarnings("unchecked") + public CommonPreference registerFloatPreference(String id, float defValue) { + if(registeredPreferences.containsKey(id)) { + return (CommonPreference) registeredPreferences.get(id); + } + FloatPreference p = new FloatPreference(id, defValue); + registeredPreferences.put(id, p); + return p; + } + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference USE_INTERNET_TO_DOWNLOAD_TILES = new BooleanPreference("use_internet_to_download_tiles", true).makeGlobal().cache(); + + public final OsmandPreference DEFAULT_APPLICATION_MODE = new EnumIntPreference( + "default_application_mode", ApplicationMode.DEFAULT, ApplicationMode.values()).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + // cache of metrics constants as they are used very often + public final OsmandPreference METRIC_SYSTEM = new EnumIntPreference( + "default_metric_system", MetricsConstants.KILOMETERS_AND_METERS, MetricsConstants.values()).makeGlobal().cache(); + + // this value string is synchronized with settings_pref.xml preference name + // cache of metrics constants as they are used very often + public final OsmandPreference DIRECTION_STYLE = new EnumIntPreference( + "direction_style", RelativeDirectionStyle.SIDEWISE, RelativeDirectionStyle.values()).makeGlobal().cache(); + + // this value string is synchronized with settings_pref.xml preference name + // cache of metrics constants as they are used very often + public final OsmandPreference ACCESSIBILITY_MODE = new EnumIntPreference( + "accessibility_mode", AccessibilityMode.DEFAULT, AccessibilityMode.values()).makeGlobal().cache(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USE_TRACKBALL_FOR_MOVEMENTS = + new BooleanPreference("use_trackball_for_movements", true).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference ZOOM_BY_TRACKBALL = + new BooleanAccessibilityPreference("zoom_by_trackball", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SCROLL_MAP_BY_GESTURES = + new BooleanAccessibilityPreference("scroll_map_by_gestures", true).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USE_SHORT_OBJECT_NAMES = + new BooleanAccessibilityPreference("use_short_object_names", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference ACCESSIBILITY_EXTENSIONS = + new BooleanAccessibilityPreference("accessibility_extensions", false).makeGlobal(); + + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USE_HIGH_RES_MAPS = new BooleanPreference("use_high_res_maps", true).makeGlobal().cache(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference MAP_TEXT_SIZE = new FloatPreference("map_text_size", 1.0f).makeProfile().cache(); + + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SHOW_POI_OVER_MAP = new BooleanPreference("show_poi_over_map", false).makeGlobal(); + + public final OsmandPreference SHOW_POI_LABEL = new BooleanPreference("show_poi_label", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SHOW_TRANSPORT_OVER_MAP = new BooleanPreference("show_transport_over_map", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference PREFERRED_LOCALE = new StringPreference("preferred_locale", "").makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USER_NAME = new StringPreference("user_name", "NoName").makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USER_OSM_BUG_NAME = + new StringPreference("user_osm_bug_name", "NoName/OsmAnd").makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USER_PASSWORD = + new StringPreference("user_password", "").makeGlobal(); + + // this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition + public final OsmandPreference OFFLINE_EDITION = new BooleanPreference("offline_edition", false).makeGlobal(); + + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference DAYNIGHT_MODE = + new EnumIntPreference("daynight_mode", DayNightMode.DAY, DayNightMode.values()); + { + DAYNIGHT_MODE.makeProfile().cache(); + DAYNIGHT_MODE.setModeDefaultValue(ApplicationMode.CAR, DayNightMode.AUTO); + DAYNIGHT_MODE.setModeDefaultValue(ApplicationMode.BICYCLE, DayNightMode.AUTO); + DAYNIGHT_MODE.setModeDefaultValue(ApplicationMode.PEDESTRIAN, DayNightMode.DAY); + } + + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference ROUTER_SERVICE = + new EnumIntPreference("router_service", RouteService.OSMAND, + new RouteService[] {RouteService.OSMAND, RouteService.ORS, RouteService.YOURS}).makeProfile(); + + public final CommonPreference SNAP_TO_ROAD = new BooleanPreference("snap_to_road", false).makeProfile().cache(); + { + SNAP_TO_ROAD.setModeDefaultValue(ApplicationMode.CAR, true); + SNAP_TO_ROAD.setModeDefaultValue(ApplicationMode.BICYCLE, true); + } + + public final CommonPreference LEFT_SIDE_NAVIGATION = new BooleanPreference("left_side_navigation", false).makeGlobal(); + + + // this value string is synchronized with settings_pref.xml preference name + public static final String SAVE_CURRENT_TRACK = "save_current_track"; //$NON-NLS-1$ + public static final String LOCAL_INDEXES = "local_indexes"; //$NON-NLS-1$ + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference SAVE_TRACK_TO_GPX = new BooleanPreference("save_track_to_gpx", false).makeProfile().cache(); + { + SAVE_TRACK_TO_GPX.setModeDefaultValue(ApplicationMode.CAR, true); + SAVE_TRACK_TO_GPX.setModeDefaultValue(ApplicationMode.BICYCLE, true); + } + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference FAST_ROUTE_MODE = new BooleanPreference("fast_route_mode", true).makeProfile(); + // temporarily for new version + public final CommonPreference PRECISE_ROUTING_MODE = new BooleanPreference("precise_routing_mode", false).makeProfile(); + public final CommonPreference OPTIMAL_ROUTE_MODE = new BooleanPreference("optimal_route_mode", true).makeProfile(); + { + OPTIMAL_ROUTE_MODE.setModeDefaultValue(ApplicationMode.PEDESTRIAN, false); + } + + public final OsmandPreference SHOW_TRAFFIC_WARNINGS = new BooleanPreference("show_traffic_warnings", true).makeProfile().cache(); + public final OsmandPreference SHOW_CAMERAS = new BooleanPreference("show_cameras", true).makeProfile().cache(); + public final OsmandPreference SHOW_LANES = new BooleanPreference("show_lanes", true).makeProfile().cache(); + + public final OsmandPreference AVOID_TOLL_ROADS = new BooleanPreference("avoid_toll_roads", false).makeProfile().cache(); + public final OsmandPreference AVOID_MOTORWAY = new BooleanPreference("avoid_motorway", false).makeProfile().cache(); + public final OsmandPreference AVOID_UNPAVED_ROADS = new BooleanPreference("avoid_unpaved_roads", false).makeProfile().cache(); + public final OsmandPreference AVOID_FERRIES = new BooleanPreference("avoid_ferries", false).makeProfile().cache(); + + public final OsmandPreference PREFER_MOTORWAYS = new BooleanPreference("prefer_motorways", false).makeProfile().cache(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference SAVE_TRACK_INTERVAL = new IntPreference("save_track_interval", 5000).makeProfile(); + { + SAVE_TRACK_INTERVAL.setModeDefaultValue(ApplicationMode.CAR, 5000); + SAVE_TRACK_INTERVAL.setModeDefaultValue(ApplicationMode.BICYCLE, 10000); + SAVE_TRACK_INTERVAL.setModeDefaultValue(ApplicationMode.PEDESTRIAN, 30000); + } + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference LIVE_MONITORING = new BooleanPreference("live_monitoring", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference LIVE_MONITORING_INTERVAL = new IntPreference("live_monitoring_interval", 5000).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference LIVE_MONITORING_URL = new StringPreference("live_monitoring_url", + "http://example.com?lat={0}&lon={1}×tamp={2}&hdop={3}&altitude={4}&speed={5}").makeGlobal(); + + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SHOW_OSM_BUGS = new BooleanPreference("show_osm_bugs", false).makeGlobal(); + + public final OsmandPreference MAP_INFO_CONTROLS = new StringPreference("map_info_controls", "").makeProfile(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference DEBUG_RENDERING_INFO = new BooleanPreference("debug_rendering", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SHOW_FAVORITES = new BooleanPreference("show_favorites", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference MAP_SCREEN_ORIENTATION = + new IntPreference("map_screen_orientation", -1/*ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED*/).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference SHOW_VIEW_ANGLE = new BooleanPreference("show_view_angle", false).makeProfile().cache(); + { + SHOW_VIEW_ANGLE.setModeDefaultValue(ApplicationMode.CAR, false); + SHOW_VIEW_ANGLE.setModeDefaultValue(ApplicationMode.BICYCLE, true); + SHOW_VIEW_ANGLE.setModeDefaultValue(ApplicationMode.PEDESTRIAN, true); + } + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference AUTO_ZOOM_MAP = new BooleanPreference("auto_zoom_map", false).makeProfile(); + { + AUTO_ZOOM_MAP.setModeDefaultValue(ApplicationMode.CAR, true); + } + + // this value string is synchronized with settings_pref.xml preference name + // seconds to auto_follow + public final CommonPreference AUTO_FOLLOW_ROUTE = new IntPreference("auto_follow_route", 0).makeProfile(); + { + AUTO_FOLLOW_ROUTE.setModeDefaultValue(ApplicationMode.CAR, 15); + AUTO_FOLLOW_ROUTE.setModeDefaultValue(ApplicationMode.BICYCLE, 15); + AUTO_FOLLOW_ROUTE.setModeDefaultValue(ApplicationMode.PEDESTRIAN, 0); + } + + // this value string is synchronized with settings_pref.xml preference name + // try without AUTO_FOLLOW_ROUTE_NAV (see forum discussion 'Simplify our navigation preference menu') + //public final CommonPreference AUTO_FOLLOW_ROUTE_NAV = new BooleanPreference("auto_follow_route_navigation", true, false); + + // this value string is synchronized with settings_pref.xml preference name + public static final int ROTATE_MAP_NONE = 0; + public static final int ROTATE_MAP_BEARING = 1; + public static final int ROTATE_MAP_COMPASS = 2; + public final CommonPreference ROTATE_MAP = + new IntPreference("rotate_map", ROTATE_MAP_NONE).makeProfile().cache(); + { + ROTATE_MAP.setModeDefaultValue(ApplicationMode.CAR, ROTATE_MAP_BEARING); + ROTATE_MAP.setModeDefaultValue(ApplicationMode.BICYCLE, ROTATE_MAP_BEARING); + ROTATE_MAP.setModeDefaultValue(ApplicationMode.PEDESTRIAN, ROTATE_MAP_COMPASS); + } + + // this value string is synchronized with settings_pref.xml preference name + public static final int CENTER_CONSTANT = 0; + public static final int BOTTOM_CONSTANT = 1; + public final CommonPreference POSITION_ON_MAP = new IntPreference("position_on_map", CENTER_CONSTANT).makeProfile(); + { + POSITION_ON_MAP.setModeDefaultValue(ApplicationMode.CAR, BOTTOM_CONSTANT); + POSITION_ON_MAP.setModeDefaultValue(ApplicationMode.BICYCLE, BOTTOM_CONSTANT); + POSITION_ON_MAP.setModeDefaultValue(ApplicationMode.PEDESTRIAN, CENTER_CONSTANT); + } + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference MAX_LEVEL_TO_DOWNLOAD_TILE = new IntPreference("max_level_download_tile", 18).makeProfile().cache(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference LEVEL_TO_SWITCH_VECTOR_RASTER = new IntPreference("level_to_switch_vector_raster", 1).makeGlobal().cache(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference AUDIO_STREAM_GUIDANCE = new IntPreference("audio_stream", + 3/*AudioManager.STREAM_MUSIC*/).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference USE_ENGLISH_NAMES = new BooleanPreference("use_english_names", false).makeGlobal(); + + public boolean usingEnglishNames(){ + return USE_ENGLISH_NAMES.get(); + } + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference MAP_ONLINE_DATA = new BooleanPreference("map_online_data", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference SHOW_DESTINATION_ARROW = new BooleanPreference("show_destination_arrow", true).makeProfile(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference MAP_OVERLAY = new StringPreference("map_overlay", null).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference MAP_UNDERLAY = new StringPreference("map_underlay", null).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference MAP_OVERLAY_TRANSPARENCY = new IntPreference("overlay_transparency", + 100).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference MAP_TRANSPARENCY = new IntPreference("map_transparency", + 255).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference MAP_TILE_SOURCES = new StringPreference("map_tile_sources", + TileSourceManager.getMapnikSource().getName()).makeGlobal(); + + public List getInternetAvailableSourceTemplates(){ + if(internetAvailableSourceTemplates == null && isInternetConnectionAvailable()){ + internetAvailableSourceTemplates = TileSourceManager.downloadTileSourceTemplates(Version.getVersionAsURLParam(ctx)); + } + return internetAvailableSourceTemplates; + } + + public CommonPreference PREVIOUS_INSTALLED_VERSION = new StringPreference("previous_installed_version", "").makeGlobal(); + + + public ITileSource getMapTileSource(boolean warnWhenSelected) { + String tileName = MAP_TILE_SOURCES.get(); + if (tileName != null) { + ITileSource ts = getTileSourceByName(tileName, warnWhenSelected); + if(ts != null){ + return ts; + } + } + return TileSourceManager.getMapnikSource(); + } + + private TileSourceTemplate checkAmongAvailableTileSources(File dir, List list){ + if (list != null) { + for (TileSourceTemplate l : list) { + if (dir.getName().equals(l.getName())) { + try { + dir.mkdirs(); + TileSourceManager.createMetaInfoFile(dir, l, true); + } catch (IOException e) { + } + return l; + } + + } + } + return null; + } + + + + public ITileSource getTileSourceByName(String tileName, boolean warnWhenSelected) { + if(tileName == null || tileName.length() == 0){ + return null; + } + List knownTemplates = TileSourceManager.getKnownSourceTemplates(); + File tPath = ctx.getAppPath(IndexConstants.TILES_INDEX_DIR); + File dir = new File(tPath, tileName); + if (!dir.exists()) { + TileSourceTemplate ret = checkAmongAvailableTileSources(dir, knownTemplates); + if (ret != null) { + return ret; + } + // try to find among other templates + ret = checkAmongAvailableTileSources(dir, getInternetAvailableSourceTemplates()); + if (ret != null) { + return ret; + } + } else if (tileName.endsWith(IndexConstants.SQLITE_EXT)) { + return ctx.getTodoAPI().newSqliteTileSource(dir, knownTemplates); + } else if (dir.isDirectory() && !dir.getName().startsWith(".")) { + TileSourceTemplate t = TileSourceManager.createTileSourceTemplate(dir); + if (warnWhenSelected && !t.isRuleAcceptable()) { + ctx.showToastMessage(R.string.warning_tile_layer_not_downloadable, dir.getName()); + } + if (!TileSourceManager.isTileSourceMetaInfoExist(dir)) { + TileSourceTemplate ret = checkAmongAvailableTileSources(dir, knownTemplates); + if (ret != null) { + t = ret; + } else { + // try to find among other templates + ret = checkAmongAvailableTileSources(dir, getInternetAvailableSourceTemplates()); + if (ret != null) { + t = ret; + } + } + + } + + return t; + } + return null; + } + + public boolean installTileSource(TileSourceTemplate toInstall){ + File tPath = ctx.getAppPath(IndexConstants.TILES_INDEX_DIR); + File dir = new File(tPath, toInstall.getName()); + dir.mkdirs(); + if(dir.exists() && dir.isDirectory()){ + try { + TileSourceManager.createMetaInfoFile(dir, toInstall, true); + } catch (IOException e) { + return false; + } + } + return true; + } + + public Map getTileSourceEntries(){ + Map map = new LinkedHashMap(); + File dir = ctx.getAppPath(IndexConstants.TILES_INDEX_DIR); + if (dir != null && dir.canRead()) { + File[] files = dir.listFiles(); + Arrays.sort(files, new Comparator(){ + @Override + public int compare(File object1, File object2) { + if(object1.lastModified() > object2.lastModified()){ + return -1; + } else if(object1.lastModified() == object2.lastModified()){ + return 0; + } + return 1; + } + + }); + if (files != null) { + for (File f : files) { + if (f.getName().endsWith(IndexConstants.SQLITE_EXT)) { + String n = f.getName(); + map.put(f.getName(), n.substring(0, n.lastIndexOf('.'))); + } else if (f.isDirectory() && !f.getName().equals(IndexConstants.TEMP_SOURCE_TO_LOAD) + && !f.getName().startsWith(".")) { + map.put(f.getName(), f.getName()); + } + } + } + } + for(TileSourceTemplate l : TileSourceManager.getKnownSourceTemplates()){ + map.put(l.getName(), l.getName()); + } + return map; + + } + + public static final String EXTERNAL_STORAGE_DIR = "external_storage_dir"; //$NON-NLS-1$ + + public File getExternalStorageDirectory() { + return new File(settingsAPI.getString(globalPreferences,EXTERNAL_STORAGE_DIR, + ctx.getExternalServiceAPI().getExternalStorageDirectory())); + } + + public boolean setExternalStorageDirectory(String externalStorageDir) { + return settingsAPI.edit(globalPreferences).putString(EXTERNAL_STORAGE_DIR, externalStorageDir).commit(); + } + + // This value is a key for saving last known location shown on the map + public static final String LAST_KNOWN_MAP_LAT = "last_known_map_lat"; //$NON-NLS-1$ + public static final String LAST_KNOWN_MAP_LON = "last_known_map_lon"; //$NON-NLS-1$ + public static final String LAST_KNOWN_MAP_ZOOM = "last_known_map_zoom"; //$NON-NLS-1$ + + public static final String MAP_LABEL_TO_SHOW = "map_label_to_show"; //$NON-NLS-1$ + public static final String MAP_LAT_TO_SHOW = "map_lat_to_show"; //$NON-NLS-1$ + public static final String MAP_LON_TO_SHOW = "map_lon_to_show"; //$NON-NLS-1$ + public static final String MAP_ZOOM_TO_SHOW = "map_zoom_to_show"; //$NON-NLS-1$ + + public LatLon getLastKnownMapLocation() { + float lat = settingsAPI.getFloat(globalPreferences,LAST_KNOWN_MAP_LAT, 0); + float lon = settingsAPI.getFloat(globalPreferences,LAST_KNOWN_MAP_LON, 0); + return new LatLon(lat, lon); + } + + public boolean isLastKnownMapLocation(){ + return settingsAPI.contains(globalPreferences,LAST_KNOWN_MAP_LAT); + } + + + public LatLon getAndClearMapLocationToShow(){ + if(!settingsAPI.contains(globalPreferences,MAP_LAT_TO_SHOW)){ + return null; + } + float lat = settingsAPI.getFloat(globalPreferences,MAP_LAT_TO_SHOW, 0); + float lon = settingsAPI.getFloat(globalPreferences,MAP_LON_TO_SHOW, 0); + settingsAPI.edit(globalPreferences).remove(MAP_LAT_TO_SHOW).commit(); + return new LatLon(lat, lon); + } + + public String getAndClearMapLabelToShow(){ + String label = settingsAPI.getString(globalPreferences,MAP_LABEL_TO_SHOW, null); + settingsAPI.edit(globalPreferences).remove(MAP_LABEL_TO_SHOW).commit(); + return label; + } + + private Object objectToShow; + public Object getAndClearObjectToShow(){ + Object objectToShow = this.objectToShow; + this.objectToShow = null; + return objectToShow; + } + + public int getMapZoomToShow() { + return settingsAPI.getInt(globalPreferences,MAP_ZOOM_TO_SHOW, 5); + } + + public void setMapLocationToShow(double latitude, double longitude, int zoom, String historyDescription, + String labelToShow, Object toShow) { + SettingsEditor edit = settingsAPI.edit(globalPreferences); + edit.putFloat(MAP_LAT_TO_SHOW, (float) latitude); + edit.putFloat(MAP_LON_TO_SHOW, (float) longitude); + if (labelToShow != null) { + edit.putString(MAP_LABEL_TO_SHOW, labelToShow); + } else { + edit.remove(MAP_LABEL_TO_SHOW); + } + edit.putInt(MAP_ZOOM_TO_SHOW, zoom); + edit.commit(); + objectToShow = toShow; + if(historyDescription != null){ + SearchHistoryHelper.getInstance(ctx).addNewItemToHistory(latitude, longitude, historyDescription); + } + } + + public void setMapLocationToShow(double latitude, double longitude, int zoom) { + setMapLocationToShow(latitude, longitude, zoom, null, null, null); + } + + public void setMapLocationToShow(double latitude, double longitude, int zoom, String historyDescription){ + setMapLocationToShow(latitude, longitude, zoom, historyDescription, historyDescription, null); + } + + // Do not use that method if you want to show point on map. Use setMapLocationToShow + public void setLastKnownMapLocation(double latitude, double longitude) { + SettingsEditor edit = settingsAPI.edit(globalPreferences); + edit.putFloat(LAST_KNOWN_MAP_LAT, (float) latitude); + edit.putFloat(LAST_KNOWN_MAP_LON, (float) longitude); + edit.commit(); + } + + public int getLastKnownMapZoom() { + return settingsAPI.getInt(globalPreferences,LAST_KNOWN_MAP_ZOOM, 5); + } + + public void setLastKnownMapZoom(int zoom) { + settingsAPI.edit(globalPreferences).putInt(LAST_KNOWN_MAP_ZOOM, zoom).commit(); + } + + public final static String POINT_NAVIGATE_LAT = "point_navigate_lat"; //$NON-NLS-1$ + public final static String POINT_NAVIGATE_LON = "point_navigate_lon"; //$NON-NLS-1$ + public final static String POINT_NAVIGATE_ROUTE = "point_navigate_route"; //$NON-NLS-1$ + public final static String POINT_NAVIGATE_DESCRIPTION = "point_navigate_description"; //$NON-NLS-1$ + public final static String INTERMEDIATE_POINTS = "intermediate_points"; //$NON-NLS-1$ + public final static String INTERMEDIATE_POINTS_DESCRIPTION = "intermediate_points_description"; //$NON-NLS-1$ + + public LatLon getPointToNavigate() { + float lat = settingsAPI.getFloat(globalPreferences,POINT_NAVIGATE_LAT, 0); + float lon = settingsAPI.getFloat(globalPreferences,POINT_NAVIGATE_LON, 0); + if (lat == 0 && lon == 0) { + return null; + } + return new LatLon(lat, lon); + } + + public String getPointNavigateDescription() { + return settingsAPI.getString(globalPreferences,POINT_NAVIGATE_DESCRIPTION, ""); + } + + + public boolean isRouteToPointNavigateAndClear(){ + boolean t = settingsAPI.contains(globalPreferences,POINT_NAVIGATE_ROUTE); + settingsAPI.edit(globalPreferences).remove(POINT_NAVIGATE_ROUTE).commit(); + return t; + } + + public boolean clearIntermediatePoints() { + return settingsAPI.edit(globalPreferences).remove(INTERMEDIATE_POINTS).commit(); + } + + public List getIntermediatePointDescriptions(int sz) { + List list = new ArrayList(); + String ip = settingsAPI.getString(globalPreferences,INTERMEDIATE_POINTS_DESCRIPTION, ""); + if (ip.trim().length() > 0) { + StringTokenizer tok = new StringTokenizer(ip, "--"); + while (tok.hasMoreTokens()) { + String d = tok.nextToken(); + list.add(d); + } + } + while(list.size() < sz) { + list.add(""); + } + return list; + } + + public List getIntermediatePoints() { + List list = new ArrayList(); + String ip = settingsAPI.getString(globalPreferences,INTERMEDIATE_POINTS, ""); + if (ip.trim().length() > 0) { + StringTokenizer tok = new StringTokenizer(ip, ","); + while (tok.hasMoreTokens()) { + String lat = tok.nextToken(); + if (!tok.hasMoreTokens()) { + break; + } + String lon = tok.nextToken(); + list.add(new LatLon(Float.parseFloat(lat), Float.parseFloat(lon))); + } + } + return list; + } + + public boolean insertIntermediatePoint(double latitude, double longitude, String historyDescription, int index, + boolean navigate) { + List ps = getIntermediatePoints(); + List ds = getIntermediatePointDescriptions(ps.size()); + ps.add(index, new LatLon(latitude, longitude)); + ds.add(index, historyDescription); + if(navigate) { + settingsAPI.edit(globalPreferences).putString(POINT_NAVIGATE_ROUTE, "true").commit(); + } + if (historyDescription != null) { + SearchHistoryHelper.getInstance(ctx).addNewItemToHistory(latitude, longitude, historyDescription); + } + return saveIntermediatePoints(ps,ds); + } + public boolean deleteIntermediatePoint( int index) { + List ps = getIntermediatePoints(); + List ds = getIntermediatePointDescriptions(ps.size()); + ps.remove(index); + ds.remove(index); + return saveIntermediatePoints(ps,ds); + } + + public boolean saveIntermediatePoints(List ps, List ds) { + StringBuilder sb = new StringBuilder(); + for(int i=0; i 0){ + sb.append(","); + } + sb.append(((float)ps.get(i).getLatitude()+"")).append(",").append(((float)ps.get(i).getLongitude()+"")); + } + StringBuilder tb = new StringBuilder(); + for (int i = 0; i < ds.size(); i++) { + if (i > 0) { + tb.append("--"); + } + if (ds.get(i) == null) { + tb.append(""); + } else { + tb.append(ds.get(i)); + } + } + return settingsAPI.edit(globalPreferences).putString(INTERMEDIATE_POINTS, sb.toString()). + putString(INTERMEDIATE_POINTS_DESCRIPTION, tb.toString()). + commit(); + } + + public boolean clearPointToNavigate() { + return settingsAPI.edit(globalPreferences).remove(POINT_NAVIGATE_LAT).remove(POINT_NAVIGATE_LON). + remove(POINT_NAVIGATE_DESCRIPTION).remove(POINT_NAVIGATE_ROUTE).commit(); + } + + public boolean setPointToNavigate(double latitude, double longitude, String historyDescription) { + return setPointToNavigate(latitude, longitude, false, historyDescription); + } + + public boolean setPointToNavigate(double latitude, double longitude, boolean navigate, String historyDescription) { + boolean add = settingsAPI.edit(globalPreferences).putFloat(POINT_NAVIGATE_LAT, (float) latitude).putFloat(POINT_NAVIGATE_LON, (float) longitude).commit(); + settingsAPI.edit(globalPreferences).putString(POINT_NAVIGATE_DESCRIPTION, historyDescription).commit(); + if(navigate) { + settingsAPI.edit(globalPreferences).putString(POINT_NAVIGATE_ROUTE, "true").commit(); + } + if(add){ + if(historyDescription != null){ + SearchHistoryHelper.getInstance(ctx).addNewItemToHistory(latitude, longitude, historyDescription); + } + } + return add; + } + + + /** + * the location of a parked car + */ + + public static final String LAST_SEARCHED_REGION = "last_searched_region"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_CITY = "last_searched_city"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_CITY_NAME = "last_searched_city_name"; //$NON-NLS-1$ + public static final String lAST_SEARCHED_POSTCODE= "last_searched_postcode"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_STREET = "last_searched_street"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_BUILDING = "last_searched_building"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_INTERSECTED_STREET = "last_searched_intersected_street"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_LAT = "last_searched_lat"; //$NON-NLS-1$ + public static final String LAST_SEARCHED_LON = "last_searched_lon"; //$NON-NLS-1$ + + public LatLon getLastSearchedPoint(){ + if(settingsAPI.contains(globalPreferences,LAST_SEARCHED_LAT) && settingsAPI.contains(globalPreferences,LAST_SEARCHED_LON)){ + return new LatLon(settingsAPI.getFloat(globalPreferences,LAST_SEARCHED_LAT, 0), + settingsAPI.getFloat(globalPreferences,LAST_SEARCHED_LON, 0)); + } + return null; + } + + public boolean setLastSearchedPoint(LatLon l){ + if(l == null){ + return settingsAPI.edit(globalPreferences).remove(LAST_SEARCHED_LAT).remove(LAST_SEARCHED_LON).commit(); + } else { + return setLastSearchedPoint(l.getLatitude(), l.getLongitude()); + } + } + + public boolean setLastSearchedPoint(double lat, double lon){ + return settingsAPI.edit(globalPreferences).putFloat(LAST_SEARCHED_LAT, (float) lat). + putFloat(LAST_SEARCHED_LON, (float) lon).commit(); + } + + public String getLastSearchedRegion() { + return settingsAPI.getString(globalPreferences, LAST_SEARCHED_REGION, ""); //$NON-NLS-1$ + } + + public boolean setLastSearchedRegion(String region, LatLon l) { + SettingsEditor edit = settingsAPI.edit(globalPreferences).putString(LAST_SEARCHED_REGION, region).putLong(LAST_SEARCHED_CITY, -1). + putString(LAST_SEARCHED_CITY_NAME, "").putString(lAST_SEARCHED_POSTCODE, ""). + putString(LAST_SEARCHED_STREET,"").putString(LAST_SEARCHED_BUILDING, ""); //$NON-NLS-1$ //$NON-NLS-2$ + if (settingsAPI.contains(globalPreferences,LAST_SEARCHED_INTERSECTED_STREET)) { + edit.putString(LAST_SEARCHED_INTERSECTED_STREET, ""); //$NON-NLS-1$ + } + boolean res = edit.commit(); + setLastSearchedPoint(l); + return res; + } + + public String getLastSearchedPostcode(){ + return settingsAPI.getString(globalPreferences, lAST_SEARCHED_POSTCODE, null); + } + + public boolean setLastSearchedPostcode(String postcode, LatLon point){ + SettingsEditor edit = settingsAPI.edit(globalPreferences).putLong(LAST_SEARCHED_CITY, -1).putString(LAST_SEARCHED_STREET, "").putString( //$NON-NLS-1$ + LAST_SEARCHED_BUILDING, "").putString(lAST_SEARCHED_POSTCODE, postcode); //$NON-NLS-1$ + if(settingsAPI.contains(globalPreferences,LAST_SEARCHED_INTERSECTED_STREET)){ + edit.putString(LAST_SEARCHED_INTERSECTED_STREET, ""); //$NON-NLS-1$ + } + boolean res = edit.commit(); + setLastSearchedPoint(point); + return res; + } + + public Long getLastSearchedCity() { + return settingsAPI.getLong(globalPreferences,LAST_SEARCHED_CITY, -1); + } + + public String getLastSearchedCityName() { + return settingsAPI.getString(globalPreferences,LAST_SEARCHED_CITY_NAME, ""); + } + + public boolean setLastSearchedCity(Long cityId, String name, LatLon point) { + SettingsEditor edit = settingsAPI.edit(globalPreferences).putLong(LAST_SEARCHED_CITY, cityId).putString(LAST_SEARCHED_CITY_NAME, name). + putString(LAST_SEARCHED_STREET, "").putString(LAST_SEARCHED_BUILDING, ""); //$NON-NLS-1$ + edit.remove(lAST_SEARCHED_POSTCODE); + if(settingsAPI.contains(globalPreferences,LAST_SEARCHED_INTERSECTED_STREET)){ + edit.putString(LAST_SEARCHED_INTERSECTED_STREET, ""); //$NON-NLS-1$ + } + boolean res = edit.commit(); + setLastSearchedPoint(point); + return res; + } + + public String getLastSearchedStreet() { + return settingsAPI.getString(globalPreferences,LAST_SEARCHED_STREET, ""); //$NON-NLS-1$ + } + + public boolean setLastSearchedStreet(String street, LatLon point) { + SettingsEditor edit = settingsAPI.edit(globalPreferences).putString(LAST_SEARCHED_STREET, street).putString(LAST_SEARCHED_BUILDING, ""); //$NON-NLS-1$ + if (settingsAPI.contains(globalPreferences,LAST_SEARCHED_INTERSECTED_STREET)) { + edit.putString(LAST_SEARCHED_INTERSECTED_STREET, ""); //$NON-NLS-1$ + } + boolean res = edit.commit(); + setLastSearchedPoint(point); + return res; + } + + public String getLastSearchedBuilding() { + return settingsAPI.getString(globalPreferences,LAST_SEARCHED_BUILDING, ""); //$NON-NLS-1$ + } + + public boolean setLastSearchedBuilding(String building, LatLon point) { + boolean res = settingsAPI.edit(globalPreferences).putString(LAST_SEARCHED_BUILDING, building).remove(LAST_SEARCHED_INTERSECTED_STREET).commit(); + setLastSearchedPoint(point); + return res; + } + + public String getLastSearchedIntersectedStreet() { + if (!settingsAPI.contains(globalPreferences,LAST_SEARCHED_INTERSECTED_STREET)) { + return null; + } + return settingsAPI.getString(globalPreferences,LAST_SEARCHED_INTERSECTED_STREET, ""); //$NON-NLS-1$ + } + + public boolean setLastSearchedIntersectedStreet(String street, LatLon l) { + setLastSearchedPoint(l); + return settingsAPI.edit(globalPreferences).putString(LAST_SEARCHED_INTERSECTED_STREET, street).commit(); + } + + public static final String SELECTED_POI_FILTER_FOR_MAP = "selected_poi_filter_for_map"; //$NON-NLS-1$ + + public boolean setPoiFilterForMap(String filterId) { + return settingsAPI.edit(globalPreferences).putString(SELECTED_POI_FILTER_FOR_MAP, filterId).commit(); + } + + public String getPoiFilterForMap(){ + return settingsAPI.getString(globalPreferences,SELECTED_POI_FILTER_FOR_MAP, null); + } + + public static final String VOICE_PROVIDER_NOT_USE = "VOICE_PROVIDER_NOT_USE"; + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference VOICE_PROVIDER = new StringPreference("voice_provider", null).makeProfile(); + + // this value string is synchronized with settings_pref.xml preference name + //public final OsmandPreference USE_COMPASS_IN_NAVIGATION = new BooleanPreference("use_compass_navigation", true).makeProfile().cache(); + public final CommonPreference USE_COMPASS_IN_NAVIGATION = new BooleanPreference("use_compass_navigation", true).makeProfile().cache(); + { + USE_COMPASS_IN_NAVIGATION.setModeDefaultValue(ApplicationMode.CAR, true); + } + + // this value string is synchronized with settings_pref.xml preference name + public final CommonPreference RENDERER = new StringPreference("renderer", RendererRegistry.DEFAULT_RENDER) { + { + makeProfile(); + } + @Override + protected boolean setValue(Object prefs, String val) { + if(val == null){ + val = RendererRegistry.DEFAULT_RENDER; + } + RenderingRulesStorage loaded = ctx.getRendererRegistry().getRenderer(val); + if (loaded != null) { + super.setValue(prefs, val); + return true; + } + return false; + }; + }; + + + Map> customRendersProps = new LinkedHashMap>(); + public CommonPreference getCustomRenderProperty(String attrName){ + if(!customRendersProps.containsKey(attrName)){ + customRendersProps.put(attrName, new StringPreference("nrenderer_"+attrName, "").makeProfile()); + } + return customRendersProps.get(attrName); + } + { + CommonPreference pref = getCustomRenderProperty("appMode"); + pref.setModeDefaultValue(ApplicationMode.CAR, "car"); + pref.setModeDefaultValue(ApplicationMode.PEDESTRIAN, "pedestrian"); + pref.setModeDefaultValue(ApplicationMode.BICYCLE, "bicycle"); + } + + Map> customBooleanRendersProps = new LinkedHashMap>(); + public CommonPreference getCustomRenderBooleanProperty(String attrName){ + if(!customRendersProps.containsKey(attrName)){ + customBooleanRendersProps.put(attrName, new BooleanPreference("nrenderer_"+attrName, false).makeProfile()); + } + return customBooleanRendersProps.get(attrName); + } + + public final OsmandPreference VOICE_MUTE = new BooleanPreference("voice_mute", false).makeGlobal(); + + // for background service + public final OsmandPreference MAP_ACTIVITY_ENABLED = new BooleanPreference("map_activity_enabled", false).makeGlobal(); + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SAFE_MODE = new BooleanPreference("safe_mode", false).makeGlobal(); + + public final OsmandPreference NATIVE_RENDERING_FAILED = new BooleanPreference("native_rendering_failed_init", false).makeGlobal(); + + + // this value string is synchronized with settings_pref.xml preference name + public static final String SERVICE_OFF_ENABLED = "service_off_enabled"; //$NON-NLS-1$ + + // this value string is synchronized with settings_pref.xml preference name + public final OsmandPreference SERVICE_OFF_INTERVAL = new IntPreference("service_off_interval", + 5 * 60 * 1000).makeGlobal(); + + public final CommonPreference SHOW_CURRENT_GPX_TRACK = + new BooleanPreference("show_current_gpx_track", false).makeGlobal().cache(); + + public final OsmandPreference CONTRIBUTION_INSTALL_APP_DATE = new StringPreference("CONTRIBUTION_INSTALL_APP_DATE", null).makeGlobal(); + + + public final OsmandPreference FOLLOW_THE_ROUTE = new BooleanPreference("follow_to_route", false).makeGlobal(); + public final OsmandPreference FOLLOW_THE_GPX_ROUTE = new StringPreference("follow_gpx", null).makeGlobal(); + + public final OsmandPreference SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME = + new BooleanPreference("show_arrival_time", true).makeGlobal(); + + + // UI boxes + public final CommonPreference TRANSPARENT_MAP_THEME = + new BooleanPreference("transparent_map_theme", true).makeProfile(); + { + TRANSPARENT_MAP_THEME.setModeDefaultValue(ApplicationMode.CAR, false); + TRANSPARENT_MAP_THEME.setModeDefaultValue(ApplicationMode.BICYCLE, false); + TRANSPARENT_MAP_THEME.setModeDefaultValue(ApplicationMode.PEDESTRIAN, true); + } + + public final CommonPreference FLUORESCENT_OVERLAYS = + new BooleanPreference("fluorescent_overlays", false).makeGlobal().cache(); + + + public final CommonPreference SHOW_RULER = + new BooleanPreference("show_ruler", true).makeProfile().cache(); + + + + public final OsmandPreference NUMBER_OF_FREE_DOWNLOADS = new IntPreference("free_downloads_v1", 0).makeGlobal(); + + public boolean checkFreeDownloadsNumberZero(){ + if(!settingsAPI.contains(globalPreferences,NUMBER_OF_FREE_DOWNLOADS.getId())){ + NUMBER_OF_FREE_DOWNLOADS.set(0); + return true; + } + return false; + } + + public enum DayNightMode { + AUTO(R.string.daynight_mode_auto), + DAY(R.string.daynight_mode_day), + NIGHT(R.string.daynight_mode_night), + SENSOR(R.string.daynight_mode_sensor); + + private final int key; + + DayNightMode(int key) { + this.key = key; + } + + public String toHumanString(ClientContext ctx){ + return ctx.getString(key); + } + + public boolean isSensor() { + return this == SENSOR; + } + + public boolean isAuto() { + return this == AUTO; + } + + public boolean isDay() { + return this == DAY; + } + + public boolean isNight() { + return this == NIGHT; + } + + public static DayNightMode[] possibleValues(ClientContext context) { + if (context.getExternalServiceAPI().isLightSensorEnabled()) { + return DayNightMode.values(); + } else { + return new DayNightMode[] { AUTO, DAY, NIGHT }; + } + } + + } + + public enum MetricsConstants { + KILOMETERS_AND_METERS(R.string.si_km_m,"km-m"), + MILES_AND_FOOTS(R.string.si_mi_foots,"mi-f"), + MILES_AND_YARDS(R.string.si_mi_yard,"mi-y"); + + private final int key; + private final String ttsString; + + MetricsConstants(int key, String ttsString) { + this.key = key; + this.ttsString = ttsString; + } + + public String toHumanString(ClientContext ctx){ + return ctx.getString(key); + } + + public String toTTSString(){ + return ttsString; + } + + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/PoiFilter.java b/OsmAnd-java/src/net/osmand/plus/PoiFilter.java new file mode 100644 index 0000000000..da66fd6287 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/PoiFilter.java @@ -0,0 +1,322 @@ +package net.osmand.plus; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import net.osmand.IndexConstants; +import net.osmand.ResultMatcher; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.util.MapUtils; + +public class PoiFilter { + + public final static String STD_PREFIX = "std_"; //$NON-NLS-1$ + public final static String USER_PREFIX = "user_"; //$NON-NLS-1$ + public final static String CUSTOM_FILTER_ID = USER_PREFIX + "custom_id"; //$NON-NLS-1$ + public final static String BY_NAME_FILTER_ID = USER_PREFIX + "by_name"; //$NON-NLS-1$ + + private Map> acceptedTypes = new LinkedHashMap>(); + private String filterByName = null; + + protected String filterId; + protected String name; + protected String nameFilter; + protected boolean isStandardFilter; + + protected final ClientContext application; + + protected int distanceInd = 1; + // in kilometers + protected double[] distanceToSearchValues = new double[] {1, 2, 3, 5, 10, 30, 100, 250 }; + + + // constructor for standard filters + public PoiFilter(AmenityType type, ClientContext application){ + this.application = application; + isStandardFilter = true; + filterId = STD_PREFIX + type; + name = type == null ? application.getString(R.string.poi_filter_closest_poi) : OsmAndFormatter.toPublicString(type, + application); //$NON-NLS-1$ + if(type == null){ + initSearchAll(); + } else { + acceptedTypes.put(type, null); + } + } + + // constructor for user defined filters + public PoiFilter(String name, String filterId, Map> acceptedTypes, ClientContext app){ + application = app; + isStandardFilter = false; + if(filterId == null){ + filterId = USER_PREFIX + name.replace(' ', '_').toLowerCase(); + } + this.filterId = filterId; + this.name = name; + if(acceptedTypes == null){ + initSearchAll(); + } else { + this.acceptedTypes.putAll(acceptedTypes); + } + } + + public void setNameFilter(String nameFilter) { + if(nameFilter != null) { + this.nameFilter = nameFilter.toLowerCase(); + } else { + clearNameFilter(); + } + } + + public String getNameFilter() { + return nameFilter; + } + + public void clearNameFilter(){ + nameFilter = null; + } + + private void initSearchAll(){ + for(AmenityType t : AmenityType.values()){ + acceptedTypes.put(t, null); + } + distanceToSearchValues = new double[] {0.5, 1, 2, 3, 5, 10, 15, 30, 100}; + } + + + public boolean isSearchFurtherAvailable(){ + return distanceInd < distanceToSearchValues.length - 1; + } + + + public List searchFurther(double latitude, double longitude, ResultMatcher matcher){ + if(distanceInd < distanceToSearchValues.length - 1){ + distanceInd ++; + } + List amenityList = searchAmenities( latitude, longitude, matcher); + MapUtils.sortListOfMapObject(amenityList, latitude, longitude); + + return amenityList; + } + + public String getSearchArea(){ + double val = distanceToSearchValues[distanceInd]; + if(val >= 1){ + return " < " + ((int) val)+ " " + application.getString(R.string.km); //$NON-NLS-1$//$NON-NLS-2$ + } else { + return " < 500 " + application.getString(R.string.m); //$NON-NLS-1$ + } + } + + public void clearPreviousZoom(){ + distanceInd = 0; + } + + public List initializeNewSearch(double lat, double lon, int firstTimeLimit, ResultMatcher matcher){ + clearPreviousZoom(); + List amenityList = searchAmenities(lat, lon, matcher); + MapUtils.sortListOfMapObject(amenityList, lat, lon); + if (firstTimeLimit > 0) { + while (amenityList.size() > firstTimeLimit) { + amenityList.remove(amenityList.size() - 1); + } + } + return amenityList; + } + + private List searchAmenities(double lat, double lon, ResultMatcher matcher) { + double baseDistY = MapUtils.getDistance(lat, lon, lat - 1, lon); + double baseDistX = MapUtils.getDistance(lat, lon, lat, lon - 1); + double distance = distanceToSearchValues[distanceInd] * 1000; + + double topLatitude = Math.min(lat + (distance/ baseDistY ), 84.); + double bottomLatitude = Math.max(lat - (distance/ baseDistY ), -84.); + double leftLongitude = Math.max(lon - (distance / baseDistX), -180); + double rightLongitude = Math.min(lon + (distance/ baseDistX), 180); + + return searchAmenities(lat, lon, topLatitude, bottomLatitude, leftLongitude, rightLongitude, matcher); + } + + public ResultMatcher getResultMatcher(final ResultMatcher matcher){ + final String filter = nameFilter; + if(filter != null) { + final boolean en = application.getSettings().USE_ENGLISH_NAMES.get(); + return new ResultMatcher() { + @Override + public boolean publish(Amenity object) { + if(!OsmAndFormatter.getPoiStringWithoutType(object, en).toLowerCase().contains(filter) || + (matcher != null && !matcher.publish(object))) { + return false; + } + return true; + } + + @Override + public boolean isCancelled() { + return false || (matcher != null && matcher.isCancelled()); + } + }; + } + return matcher; + } + + protected List searchAmenities(double lat, double lon, double topLatitude, + double bottomLatitude, double leftLongitude, double rightLongitude, final ResultMatcher matcher) { + + return application.getInternalAPI().searchAmenities(this, + topLatitude, leftLongitude, bottomLatitude, rightLongitude, lat, lon, matcher); + } + + public List searchAgain(double lat, double lon) { + List amenityList = searchAmenities(lat, lon, null); + MapUtils.sortListOfMapObject(amenityList, lat, lon); + return amenityList; + } + + public String getName(){ + return name; + } + + /** + * @param type + * @return null if all subtypes are accepted/ empty list if type is not accepted at all + */ + public Set getAcceptedSubtypes(AmenityType type){ + if(!acceptedTypes.containsKey(type)){ + return Collections.emptySet(); + } + return acceptedTypes.get(type); + } + + public boolean isTypeAccepted(AmenityType t){ + return acceptedTypes.containsKey(t); + } + + public boolean acceptTypeSubtype(AmenityType t, String subtype){ + if(!acceptedTypes.containsKey(t)){ + return false; + } + LinkedHashSet set = acceptedTypes.get(t); + if(set == null){ + return true; + } + return set.contains(subtype); + } + + public void clearFilter(){ + acceptedTypes = new LinkedHashMap>(); + } + + public boolean areAllTypesAccepted(){ + if(AmenityType.values().length == acceptedTypes.size()){ + for(AmenityType a : acceptedTypes.keySet()){ + if(acceptedTypes.get(a) != null){ + return false; + } + } + return true; + } + return false; + } + + + public void setTypeToAccept(AmenityType type, boolean accept){ + if(accept){ + acceptedTypes.put(type, new LinkedHashSet()); + } else { + acceptedTypes.remove(type); + } + } + + public void setMapToAccept(Map> newMap) { + Iterator>> iterator = newMap.entrySet().iterator(); + acceptedTypes.clear(); + while(iterator.hasNext()){ + Entry> e = iterator.next(); + if(e.getValue() == null){ + acceptedTypes.put(e.getKey(), null); + } else { + acceptedTypes.put(e.getKey(), new LinkedHashSet(e.getValue())); + } + } + } + + public String buildSqlWhereFilter(){ + if(areAllTypesAccepted()){ + return null; + } + assert IndexConstants.POI_TABLE != null : "use constants here to show table usage "; //$NON-NLS-1$ + if(acceptedTypes.size() == 0){ + return "1 > 1"; //$NON-NLS-1$ + } + StringBuilder b = new StringBuilder(); + b.append("("); //$NON-NLS-1$ + boolean first = true; + for(AmenityType a : acceptedTypes.keySet()){ + if(first){ + first = false; + } else { + b.append(" OR "); //$NON-NLS-1$ + } + b.append("(type = '").append(AmenityType.valueToString(a)).append("'"); //$NON-NLS-1$ //$NON-NLS-2$ + if(acceptedTypes.get(a) != null){ + LinkedHashSet list = acceptedTypes.get(a); + b.append(" AND subtype IN ("); //$NON-NLS-1$ + boolean bfirst = true; + for(String s : list){ + if(bfirst){ + bfirst = false; + } else { + b.append(", "); //$NON-NLS-1$ + } + b.append("'").append(s).append("'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + b.append(")"); //$NON-NLS-1$ + } + b.append(")"); //$NON-NLS-1$ + } + b.append(")"); //$NON-NLS-1$ + return b.toString(); + } + + public Map> getAcceptedTypes(){ + return new LinkedHashMap>(acceptedTypes); + } + + public void selectSubTypesToAccept(AmenityType t, LinkedHashSet accept){ + acceptedTypes.put(t, accept); + } + + public String getFilterId(){ + return filterId; + } + + + public String getFilterByName() { + return filterByName; + } + + public void setFilterByName(String filterByName) { + this.filterByName = filterByName; + } + + public boolean isStandardFilter(){ + return isStandardFilter; + } + + public void setStandardFilter(boolean isStandardFilter) { + this.isStandardFilter = isStandardFilter; + } + + public ClientContext getApplication() { + return application; + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/PoiFiltersHelper.java b/OsmAnd-java/src/net/osmand/plus/PoiFiltersHelper.java new file mode 100644 index 0000000000..50ff025d24 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/PoiFiltersHelper.java @@ -0,0 +1,488 @@ +package net.osmand.plus; + + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; + +import net.osmand.data.AmenityType; +import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; +import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; +import net.osmand.plus.api.SQLiteAPI.SQLiteStatement; + +public class PoiFiltersHelper { + private final ClientContext application; + + private NameFinderPoiFilter nameFinderPOIFilter; + private List cacheUserDefinedFilters; + private List cacheOsmDefinedFilters; + + private static final String UDF_CAR_AID = "car_aid"; + private static final String UDF_FOR_TOURISTS = "for_tourists"; + private static final String UDF_FOOD_SHOP = "food_shop"; + private static final String UDF_FUEL = "fuel"; + private static final String UDF_SIGHTSEEING = "sightseeing"; + private static final String UDF_EMERGENCY = "emergency"; + private static final String UDF_PUBLIC_TRANSPORT = "public_transport"; + private static final String UDF_ENTERTAINMENT = "entertainment"; + private static final String UDF_ACCOMODATION = "accomodation"; + private static final String UDF_RESTAURANTS = "restaurants"; + private static final String UDF_PARKING = "parking"; + + private static final String[] DEL = new String[] {}; + + public PoiFiltersHelper(ClientContext application){ + this.application = application; + } + public NameFinderPoiFilter getNameFinderPOIFilter() { + if(nameFinderPOIFilter == null){ + nameFinderPOIFilter = new NameFinderPoiFilter(application); + } + return nameFinderPOIFilter; + } + + + public PoiFilter getFilterById(String filterId){ + if(filterId == null){ + return null; + } + if(filterId.equals(NameFinderPoiFilter.FILTER_ID)){ + return getNameFinderPOIFilter(); + } + if(filterId.startsWith(PoiFilter.USER_PREFIX)){ + List filters = getUserDefinedPoiFilters(); + for(PoiFilter f : filters){ + if(f.getFilterId().equals(filterId)){ + return f; + } + } + } else if(filterId.startsWith(PoiFilter.STD_PREFIX)){ + List filters = getOsmDefinedPoiFilters(); + for(PoiFilter f : filters){ + if(f.getFilterId().equals(filterId)){ + return f; + } + } + } + return null; + } + + private void putAll(Map> types, AmenityType tp){ + types.put(tp, null); + } + + private void putValues(Map> types, AmenityType tp,String... vls){ + LinkedHashSet list = new LinkedHashSet(); + for(String v: vls){ + list.add(v); + } + types.put(tp, list); + } + + private List getUserDefinedDefaultFilters() { + List filters = new ArrayList(); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_car_aid), PoiFilter.USER_PREFIX + UDF_CAR_AID, + configureDefaultUserDefinedFilter(null, UDF_CAR_AID), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_for_tourists), PoiFilter.USER_PREFIX + UDF_FOR_TOURISTS, + configureDefaultUserDefinedFilter(null, UDF_FOR_TOURISTS), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_fuel), PoiFilter.USER_PREFIX + UDF_FUEL, + configureDefaultUserDefinedFilter(null, UDF_FUEL), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_food_shop), PoiFilter.USER_PREFIX + UDF_FOOD_SHOP, + configureDefaultUserDefinedFilter(null, UDF_FOOD_SHOP), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_sightseeing), PoiFilter.USER_PREFIX + UDF_SIGHTSEEING, + configureDefaultUserDefinedFilter(null, UDF_SIGHTSEEING), application)); + + // UDF_EMERGENCY = "emergency"; + // UDF_ENTERTAINMENT = "entertainment"; + filters.add(new PoiFilter(application.getString(R.string.poi_filter_accomodation), PoiFilter.USER_PREFIX + UDF_ACCOMODATION, + configureDefaultUserDefinedFilter(null, UDF_ACCOMODATION), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_restaurants), PoiFilter.USER_PREFIX + UDF_RESTAURANTS, + configureDefaultUserDefinedFilter(null, UDF_RESTAURANTS), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_public_transport), + PoiFilter.USER_PREFIX + UDF_PUBLIC_TRANSPORT, configureDefaultUserDefinedFilter(null, UDF_PUBLIC_TRANSPORT), application)); + filters.add(new PoiFilter(application.getString(R.string.poi_filter_parking), PoiFilter.USER_PREFIX + UDF_PARKING, + configureDefaultUserDefinedFilter(null, UDF_PARKING), application)); + return filters; + } + + private Map> configureDefaultUserDefinedFilter(Map> types, String key) { + if(types == null) { + types = new LinkedHashMap>(); + } + if(UDF_CAR_AID.equals(key)){ + putValues(types, AmenityType.TRANSPORTATION, "fuel", "car_wash", "car_repair","car", "car_sharing"); + putValues(types, AmenityType.SHOP, "fuel", "car_wash", "car_repair","car", "car_parts"); + } else if(UDF_SIGHTSEEING.equals(key)){ + putAll(types, AmenityType.HISTORIC); + putAll(types, AmenityType.TOURISM); + putAll(types, AmenityType.OSMWIKI); + putValues(types, AmenityType.OTHER, "place_of_worship"); + } else if(UDF_FOR_TOURISTS.equals(key)){ + putAll(types, AmenityType.HISTORIC); + putAll(types, AmenityType.TOURISM); + putAll(types, AmenityType.FINANCE); + putAll(types, AmenityType.OSMWIKI); + putValues(types, AmenityType.OTHER, "place_of_worship", "internet_access_wlan", "internet_access_wired", + "internet_access_terminal", "internet_access_public", "internet_access_service", + "embassy","emergency_phone","marketplace", + "post_office","telephone", "toilets"); + } else if(UDF_FUEL.equals(key)){ + putValues(types, AmenityType.TRANSPORTATION, "fuel"); + } else if (UDF_FOOD_SHOP.equals(key)) { + putValues(types, AmenityType.SHOP, "alcohol", "bakery", "beverages", "butcher", "convenience", "department_store", + "convenience", "farm", "general", "ice_cream", "kiosk", "supermarket", "variety_store"); + } else if (UDF_SIGHTSEEING.equals(key)) { + putAll(types, AmenityType.HISTORIC); + putValues(types, AmenityType.TOURISM, "attraction", + "artwork","zoo","theme_park", "museum","viewpoint"); + putValues(types, AmenityType.OTHER, "place_of_worship"); + } else if (UDF_ACCOMODATION.equals(key)) { + putValues(types, AmenityType.TOURISM, "camp_site", + "caravan_site","picnic_site","alpine_hut", "chalet","guest_house", + "hostel", "hotel","motel"); + } else if (UDF_PARKING.equals(key)) { + putValues(types, AmenityType.TRANSPORTATION, "parking", + "bicycle_parking"); + } else if (UDF_PUBLIC_TRANSPORT.equals(key)) { + putValues(types, AmenityType.TRANSPORTATION, "public_transport_stop_position", "public_transport_platform", + "public_transport_station", + // railway + "railway_platform", "railway_station", "halt", "tram_stop", "subway_entrance", "railway_buffer_stop", + // bus, cars, bicycle + "bus_stop", "platform", "ferry_terminal", "taxi", "bicycle_rental", "bus_station", "car_rental", "car_sharing", + // aero + "airport", "aerodrome", "terminal", "gate", + // aerial ways ( hide ways) + // "aerialway_cable_car", "aerialway_gondola", "aerialway_chair_lift", "aerialway_mixed_lift", "aerialway_drag_lift", "aerialway_goods", + "aerialway_station" + // ways (hide ways) + // "rail", "tram", "light_rail", "subway", "railway_narrow_gauge", "railway_monorail", "railway_funicular" + ); + } else if (UDF_RESTAURANTS.equals(key)) { + putValues(types, AmenityType.SUSTENANCE, "restaurant", + "cafe", "food_court", "fast_food", "pub", "bar", "biergarten"); + } else if (UDF_EMERGENCY.equals(key)) { + putAll(types, AmenityType.HEALTHCARE); + putAll(types, AmenityType.EMERGENCY); + } else if (UDF_ENTERTAINMENT.equals(key)) { + putAll(types, AmenityType.ENTERTAINMENT); + } + + return types; + } + + + public List getUserDefinedPoiFilters(){ + if(cacheUserDefinedFilters == null){ + cacheUserDefinedFilters = new ArrayList(); + PoiFilter filter = new PoiFilter(application.getString(R.string.poi_filter_custom_filter), PoiFilter.CUSTOM_FILTER_ID, + new LinkedHashMap>(), application); //$NON-NLS-1$ + filter.setStandardFilter(true); + cacheUserDefinedFilters.add(filter); + filter = new SearchByNameFilter(application); + cacheUserDefinedFilters.add(filter); + PoiFilterDbHelper helper = openDbHelper(); + List userDefined = helper.getFilters(helper.getReadableDatabase()); + final Collator instance = Collator.getInstance(); + Collections.sort(userDefined, new Comparator() { + @Override + public int compare(PoiFilter object1, PoiFilter object2) { + return instance.compare(object1.getName(), object2.getName()); + } + }); + cacheUserDefinedFilters.addAll(userDefined); + helper.close(); + } + return Collections.unmodifiableList(cacheUserDefinedFilters); + } + + public static String getOsmDefinedFilterId(AmenityType t){ + return PoiFilter.STD_PREFIX + t; + } + + public void updateFilters(boolean onlyAddFilters){ + PoiFilterDbHelper helper = openDbHelper(); + helper.upgradeFilters(helper.getWritableDatabase(), onlyAddFilters); + helper.close(); + } + + + public List getOsmDefinedPoiFilters(){ + if(cacheOsmDefinedFilters == null){ + cacheOsmDefinedFilters = new ArrayList(); + for(AmenityType t : AmenityType.values()){ + cacheOsmDefinedFilters.add(new PoiFilter(t, application)); + } + final Collator instance = Collator.getInstance(); + Collections.sort(cacheOsmDefinedFilters, new Comparator() { + @Override + public int compare(PoiFilter object1, PoiFilter object2) { + return instance.compare(object1.getName(), object2.getName()); + } + }); + cacheOsmDefinedFilters.add(0, new PoiFilter(null, application)); + } + return Collections.unmodifiableList(cacheOsmDefinedFilters); + } + + private PoiFilterDbHelper openDbHelper(){ + return new PoiFilterDbHelper(application); + } + + public boolean removePoiFilter(PoiFilter filter){ + if(filter.getFilterId().equals(PoiFilter.CUSTOM_FILTER_ID) || + filter.getFilterId().equals(PoiFilter.BY_NAME_FILTER_ID)){ + return false; + } + PoiFilterDbHelper helper = openDbHelper(); + if(helper == null){ + return false; + } + boolean res = helper.deleteFilter(helper.getWritableDatabase(), filter); + if(res){ + cacheUserDefinedFilters.remove(filter); + } + helper.close(); + return res; + } + + public boolean createPoiFilter(PoiFilter filter){ + PoiFilterDbHelper helper = openDbHelper(); + if(helper == null){ + return false; + } + boolean res = helper.addFilter(filter, helper.getWritableDatabase(), false); + if(res){ + cacheUserDefinedFilters.add(filter); + } + helper.close(); + return res; + } + + + + public boolean editPoiFilter(PoiFilter filter) { + if (filter.getFilterId().equals(PoiFilter.CUSTOM_FILTER_ID) || + filter.getFilterId().equals(PoiFilter.BY_NAME_FILTER_ID)) { + return false; + } + PoiFilterDbHelper helper = openDbHelper(); + if (helper != null) { + boolean res = helper.editFilter(helper.getWritableDatabase(), filter); + helper.close(); + return res; + } + return false; + } + + + public class PoiFilterDbHelper { + + public static final String DATABASE_NAME = "poi_filters"; //$NON-NLS-1$ + private static final int DATABASE_VERSION = 2; + private static final String FILTER_NAME = "poi_filters"; //$NON-NLS-1$ + private static final String FILTER_COL_NAME = "name"; //$NON-NLS-1$ + private static final String FILTER_COL_ID = "id"; //$NON-NLS-1$ + private static final String FILTER_COL_FILTERBYNAME = "filterbyname"; //$NON-NLS-1$ + private static final String FILTER_TABLE_CREATE = "CREATE TABLE " + FILTER_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$ + FILTER_COL_NAME + ", " + FILTER_COL_ID + ", " + FILTER_COL_FILTERBYNAME + ");"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + + private static final String CATEGORIES_NAME = "categories"; //$NON-NLS-1$ + private static final String CATEGORIES_FILTER_ID = "filter_id"; //$NON-NLS-1$ + private static final String CATEGORIES_COL_CATEGORY = "category"; //$NON-NLS-1$ + private static final String CATEGORIES_COL_SUBCATEGORY = "subcategory"; //$NON-NLS-1$ + private static final String CATEGORIES_TABLE_CREATE = "CREATE TABLE " + CATEGORIES_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$ + CATEGORIES_FILTER_ID + ", " + CATEGORIES_COL_CATEGORY + ", " + CATEGORIES_COL_SUBCATEGORY + ");"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private ClientContext context; + private SQLiteConnection conn; + + PoiFilterDbHelper(ClientContext context) { + this.context = context; + } + + public SQLiteConnection getWritableDatabase() { + return openConnection(false); + } + + public void close() { + if(conn != null) { + conn.close(); + conn = null; + } + } + + public SQLiteConnection getReadableDatabase() { + return openConnection(true); + } + + private SQLiteConnection openConnection(boolean readonly) { + conn = context.getSQLiteAPI().getOrCreateDatabase(DATABASE_NAME, readonly); + if (conn.getVersion() == 0 || DATABASE_VERSION != conn.getVersion()) { + if (readonly) { + conn.close(); + conn = context.getSQLiteAPI().getOrCreateDatabase(DATABASE_NAME, readonly); + } + if (conn.getVersion() == 0) { + conn.setVersion(DATABASE_VERSION); + onCreate(conn); + } else { + onUpgrade(conn, conn.getVersion(), DATABASE_VERSION); + } + + } + return conn; + } + + public void onCreate(SQLiteConnection conn) { + conn.execSQL(FILTER_TABLE_CREATE); + conn.execSQL(CATEGORIES_TABLE_CREATE); + upgradeFilters(conn, true); + } + + public void upgradeFilters(SQLiteConnection conn, boolean onlyAdd) { + List filters = PoiFilterDbHelper.this.getFilters(conn); + List def = getUserDefinedDefaultFilters(); + for(PoiFilter f : filters){ + PoiFilter std = null; + for(PoiFilter d : def){ + if(f.getFilterId().equals(d.getFilterId())){ + std = d; + break; + } + } + for(String toDel : DEL) { + if(f.getFilterId().equals(toDel)) { + deleteFilter(conn, f); + } + } + if(std != null){ + if(!onlyAdd){ + editFilter(conn, std); + } else { + updateName(conn, std); + } + def.remove(std); + } + } + for(PoiFilter d : def){ + addFilter(d, conn, false); + } + } + + public void onUpgrade(SQLiteConnection conn, int oldVersion, int newVersion) { + if (newVersion == 2 || newVersion == 3) { + upgradeFilters(conn, false); + } else { + upgradeFilters(conn, true); + } + conn.setVersion(newVersion); + } + + protected boolean addFilter(PoiFilter p, SQLiteConnection db, boolean addOnlyCategories){ + if(db != null){ + if(!addOnlyCategories){ + db.execSQL("INSERT INTO " + FILTER_NAME + " VALUES (?, ?, ?)",new Object[]{p.getName(), p.getFilterId(), p.getFilterByName()}); //$NON-NLS-1$ //$NON-NLS-2$ + } + Map> types = p.getAcceptedTypes(); + SQLiteStatement insertCategories = db.compileStatement("INSERT INTO " + CATEGORIES_NAME + " VALUES (?, ?, ?)"); //$NON-NLS-1$ //$NON-NLS-2$ + for(AmenityType a : types.keySet()){ + if(types.get(a) == null){ + insertCategories.bindString(1, p.getFilterId()); + insertCategories.bindString(2, AmenityType.valueToString(a)); + insertCategories.bindNull(3); + insertCategories.execute(); + } else { + for(String s : types.get(a)){ + insertCategories.bindString(1, p.getFilterId()); + insertCategories.bindString(2, AmenityType.valueToString(a)); + insertCategories.bindString(3, s); + insertCategories.execute(); + } + } + } + insertCategories.close(); + return true; + } + return false; + } + + protected List getFilters(SQLiteConnection conn){ + ArrayList list = new ArrayList(); + if(conn != null){ + SQLiteCursor query = conn.rawQuery("SELECT " + CATEGORIES_FILTER_ID +", " + CATEGORIES_COL_CATEGORY +"," + CATEGORIES_COL_SUBCATEGORY +" FROM " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + CATEGORIES_NAME, null); + Map>> map = new LinkedHashMap>>(); + if(query.moveToFirst()){ + do { + String filterId = query.getString(0); + if(!map.containsKey(filterId)){ + map.put(filterId, new LinkedHashMap>()); + } + Map> m = map.get(filterId); + AmenityType a = AmenityType.fromString(query.getString(1)); + String subCategory = query.getString(2); + if(subCategory == null){ + m.put(a, null); + } else { + if(m.get(a) == null){ + m.put(a, new LinkedHashSet()); + } + m.get(a).add(subCategory); + } + } while(query.moveToNext()); + } + query.close(); + + query = conn.rawQuery("SELECT " + FILTER_COL_ID +", " + FILTER_COL_NAME +"," + FILTER_COL_FILTERBYNAME +" FROM " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + FILTER_NAME, null); + if(query.moveToFirst()){ + do { + String filterId = query.getString(0); + if(map.containsKey(filterId)){ + PoiFilter filter = new PoiFilter(query.getString(1), filterId, map.get(filterId), application); + filter.setFilterByName(query.getString(2)); + list.add(filter); + } + } while(query.moveToNext()); + } + query.close(); + } + return list; + } + + protected boolean editFilter(SQLiteConnection conn, PoiFilter filter) { + if (conn != null) { + conn.execSQL("DELETE FROM " + CATEGORIES_NAME + " WHERE " + CATEGORIES_FILTER_ID + " = ?", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + new Object[] { filter.getFilterId() }); + addFilter(filter, conn, true); + updateName(conn, filter); + return true; + } + return false; + } + + private void updateName(SQLiteConnection db, PoiFilter filter) { + db.execSQL("UPDATE " + FILTER_NAME + " SET " + FILTER_COL_FILTERBYNAME + " = ?, " + FILTER_COL_NAME + " = ? " + " WHERE " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + + FILTER_COL_ID + "= ?", new Object[] { filter.getFilterByName(), filter.getName(), filter.getFilterId() }); //$NON-NLS-1$ + } + + protected boolean deleteFilter(SQLiteConnection db, PoiFilter p){ + if(db != null){ + db.execSQL("DELETE FROM " + FILTER_NAME + " WHERE " +FILTER_COL_ID + " = ?",new Object[]{p.getFilterId()}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + db.execSQL("DELETE FROM " + CATEGORIES_NAME + " WHERE " +CATEGORIES_FILTER_ID + " = ?", new Object[]{p.getFilterId()}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + return true; + } + return false; + } + + + + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/RotatedTileBox.java b/OsmAnd-java/src/net/osmand/plus/RotatedTileBox.java new file mode 100644 index 0000000000..c851fd8c7f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/RotatedTileBox.java @@ -0,0 +1,174 @@ +package net.osmand.plus; +import net.osmand.data.QuadPoint; +import net.osmand.data.QuadRect; +import net.osmand.util.MapUtils; + +public class RotatedTileBox { + private float leftTileX; + private float topTileY; + private float tileWidth; + private float tileHeight; + private float rotate; + private float zoom; + private float rotateCos; + private float rotateSin; + + public RotatedTileBox(float leftTileX, float topTileY, float tileWidth, float tileHeight, float rotate, int zoom) { + set(leftTileX, topTileY, tileWidth, tileHeight, rotate, zoom); + } + + public RotatedTileBox(RotatedTileBox r){ + set(r.leftTileX, r.topTileY, r.tileWidth, r.tileHeight, r.rotate, r.zoom); + } + + private void init() { + float rad = (float) Math.toRadians(this.rotate); + rotateCos = (float) Math.cos(rad); + rotateSin = (float) Math.sin(rad); + } + + public void set(float leftTileX, float topTileY, float tileWidth, float tileHeight, float rotate, float zoom) { + this.leftTileX = leftTileX; + if(rotate < 0){ + rotate += 360; + } else if(rotate > 360){ + rotate -= 360; + } + this.rotate = rotate; + this.tileHeight = tileHeight; + this.tileWidth = tileWidth; + this.topTileY = topTileY; + this.zoom = zoom; + init(); + } + + public float getRotateCos() { + return rotateCos; + } + + public float getRotateSin() { + return rotateSin; + } + + public float getZoom() { + return zoom; + } + + public int getIntZoom() { + return Math.round(zoom); + } + + public float getRotate() { + return rotate; + } + + public float getTileHeight() { + return tileHeight; + } + + public float getTileWidth() { + return tileWidth; + } + + public float getLeftTileX() { + return leftTileX; + } + + public float getTopTileY() { + return topTileY; + } + + public boolean containsTileBox(RotatedTileBox box) { + QuadPoint temp = new QuadPoint(); + if(box.zoom != zoom){ + throw new UnsupportedOperationException(); + } + box.calcPointTile(0, 0, temp); + if(!containsPoint(temp.x, temp.y)){ + return false; + } + box.calcPointTile(box.tileWidth, 0, temp); + if(!containsPoint(temp.x, temp.y)){ + return false; + } + box.calcPointTile(0, box.tileHeight, temp); + if(!containsPoint(temp.x, temp.y)){ + return false; + } + box.calcPointTile(box.tileWidth, box.tileHeight, temp); + if(!containsPoint(temp.x, temp.y)){ + return false; + } + return true; + } + + public QuadRect calculateLatLonBox(QuadRect rectF) { + float tx = calcPointTileX(tileWidth, 0); + float tx2 = calcPointTileX(tileWidth, tileHeight); + float tx3 = calcPointTileX(0, tileHeight); + float minTileX = Math.min(Math.min(leftTileX, tx), Math.min(tx2, tx3)) ; + float maxTileX = Math.max(Math.max(leftTileX, tx), Math.max(tx2, tx3)) ; + int max = (int) MapUtils.getPowZoom(zoom); + if(minTileX < 0){ + minTileX = 0; + } + if(maxTileX > max){ + maxTileX = max; + } + + rectF.left = (float) MapUtils.getLongitudeFromTile(zoom, minTileX); + rectF.right = (float) MapUtils.getLongitudeFromTile(zoom, maxTileX); + + float ty = calcPointTileY(tileWidth, 0); + float ty2 = calcPointTileY(tileWidth, tileHeight); + float ty3 = calcPointTileY(0, tileHeight); + + float minTileY = Math.min(Math.min(topTileY, ty), Math.min(ty2, ty3)) ; + float maxTileY = Math.max(Math.max(topTileY, ty), Math.max(ty2, ty3)) ; + if(minTileY < 0){ + minTileY = 0; + } + if(maxTileY > max){ + maxTileY = max; + } + + rectF.top = (float) MapUtils.getLatitudeFromTile(zoom, minTileY); + rectF.bottom = (float) MapUtils.getLatitudeFromTile(zoom, maxTileY); + + return rectF; + } + + public boolean containsPoint(float tileX, float tileY) { + tileX -= leftTileX; + tileY -= topTileY; + double tx = rotateCos * tileX - rotateSin * tileY; + double ty = rotateSin * tileX + rotateCos * tileY; + return tx >= 0 && tx <= tileWidth && ty >= 0 && ty <= tileHeight; + } + + protected QuadPoint calcPointTile(float dx, float dy, QuadPoint p){ + float tx = rotateCos * dx + rotateSin * dy + leftTileX; + float ty = - rotateSin * dx + rotateCos * dy + topTileY; + p.set(tx, ty); + return p; + } + + protected float calcPointTileX(float dx, float dy){ + return rotateCos * dx + rotateSin * dy + leftTileX; + } + + protected float calcPointTileY(float dx, float dy){ + return - rotateSin * dx + rotateCos * dy + topTileY; + } + + public float getRightBottomTileX() { + return calcPointTileX(tileWidth, tileHeight); + } + + public float getRightBottomTileY() { + return calcPointTileY(tileWidth, tileHeight); + } + + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/SearchByNameFilter.java b/OsmAnd-java/src/net/osmand/plus/SearchByNameFilter.java new file mode 100644 index 0000000000..88621c5b85 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/SearchByNameFilter.java @@ -0,0 +1,79 @@ +package net.osmand.plus; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; + +import net.osmand.ResultMatcher; +import net.osmand.data.Amenity; +import net.osmand.data.AmenityType; +import net.osmand.util.MapUtils; + +public class SearchByNameFilter extends PoiFilter { + + public static final String FILTER_ID = PoiFilter.BY_NAME_FILTER_ID; //$NON-NLS-1$ + + List searchedAmenities = new ArrayList(); + + private String query = ""; //$NON-NLS-1$ + + public SearchByNameFilter(ClientContext application) { + super(application.getString(R.string.poi_filter_by_name), FILTER_ID, new LinkedHashMap>(), application); + this.distanceToSearchValues = new double[] {100, 1000, 5000}; + this.isStandardFilter = true; + } + + @Override + public List searchAgain(double lat, double lon) { + MapUtils.sortListOfMapObject(searchedAmenities, lat, lon); + return searchedAmenities; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + @Override + protected List searchAmenities(double lat, double lon, double topLatitude, + double bottomLatitude, double leftLongitude, double rightLongitude, final ResultMatcher matcher) { + searchedAmenities.clear(); + final int limit = distanceInd == 0 ? 500 : -1; + + List result = application.getInternalAPI().searchAmenitiesByName(query, + topLatitude, leftLongitude, bottomLatitude, rightLongitude, lat, lon, new ResultMatcher() { + boolean elimit = false; + @Override + public boolean publish(Amenity object) { + if(limit != -1 && searchedAmenities.size() > limit) { + elimit = true; + } + if(matcher.publish(object)) { + searchedAmenities.add(object); + return true; + } + return false; + } + + @Override + public boolean isCancelled() { + return matcher.isCancelled() || elimit; + } + }); + MapUtils.sortListOfMapObject(result, lat, lon); + searchedAmenities = result; + return searchedAmenities; + } + + + public List getSearchedAmenities() { + return searchedAmenities; + } + + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/SearchHistoryHelper.java b/OsmAnd-java/src/net/osmand/plus/SearchHistoryHelper.java new file mode 100644 index 0000000000..72b3ce0fcb --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/SearchHistoryHelper.java @@ -0,0 +1,243 @@ +package net.osmand.plus; + +import java.util.ArrayList; +import java.util.List; + +import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; +import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; + +public class SearchHistoryHelper { + + private static final int HISTORY_LIMIT = 50; + private ClientContext context; + private List loadedEntries = null; + + public SearchHistoryHelper(ClientContext context) { + this.context = context; + } + + public static SearchHistoryHelper getInstance(ClientContext context){ + return new SearchHistoryHelper(context); + } + + public static class HistoryEntry { + double lat; + double lon; + String name; + + public HistoryEntry(double lat, double lon, String name){ + this.lat = lat; + this.lon = lon; + this.name = name; + + } + + public String getName() { + return name; + } + + public double getLat() { + return lat; + } + public double getLon() { + return lon; + } + } + + public List getHistoryEntries() { + if(loadedEntries == null){ + checkLoadedEntries(); + } + return loadedEntries; + } + + private HistoryItemDBHelper checkLoadedEntries(){ + HistoryItemDBHelper helper = new HistoryItemDBHelper(); + if(loadedEntries == null){ + loadedEntries = helper.getEntries(); + } + return helper; + } + + public void remove(HistoryEntry model) { + HistoryItemDBHelper helper = checkLoadedEntries(); + if(helper.remove(model)){ + loadedEntries.remove(model); + } + } + + public void removeAll() { + HistoryItemDBHelper helper = checkLoadedEntries(); + if(helper.removeAll()){ + loadedEntries.clear(); + } + } + + public void selectEntry(HistoryEntry model) { + HistoryItemDBHelper helper = checkLoadedEntries(); + int i = loadedEntries.indexOf(model); + updateModelAt(model, helper, i); + } + + private void updateModelAt(HistoryEntry model, HistoryItemDBHelper helper, int i) { + if(i == -1){ + if(helper.add(model)){ + loadedEntries.add(0, model); + if(loadedEntries.size() > HISTORY_LIMIT){ + if(helper.remove(loadedEntries.get(loadedEntries.size() - 1))){ + loadedEntries.remove(loadedEntries.size() - 1); + } + } + } + } else { + if(helper.update(model)){ + loadedEntries.remove(i); + loadedEntries.add(0, model); + } + } + } + + public HistoryEntry addNewItemToHistory(double lat, double lon, String description){ + HistoryItemDBHelper helper = checkLoadedEntries(); + int i = 0; + HistoryEntry model = new HistoryEntry(lat, lon, description); + for(HistoryEntry e : loadedEntries){ + if(description.equals(e.getName())){ + break; + } + i++; + } + if(i == loadedEntries.size()){ + i = -1; + } + if (i != 0) { + updateModelAt(model, helper, i); + } + return model; + } + + private class HistoryItemDBHelper { + + private static final String DB_NAME = "search_history"; //$NON-NLS-1$ + private static final int DB_VERSION = 1; + private static final String HISTORY_TABLE_NAME = "history"; //$NON-NLS-1$ + private static final String HISTORY_COL_NAME = "name"; //$NON-NLS-1$ + private static final String HISTORY_COL_TIME = "time"; //$NON-NLS-1$ + private static final String HISTORY_COL_TYPE = "type"; //$NON-NLS-1$ + private static final String HISTORY_COL_LAT = "latitude"; //$NON-NLS-1$ + private static final String HISTORY_COL_LON = "longitude"; //$NON-NLS-1$ + private static final String HISTORY_TABLE_CREATE = "CREATE TABLE " + HISTORY_TABLE_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$ + HISTORY_COL_NAME + " TEXT, " + HISTORY_COL_TIME + " long, " + HISTORY_COL_TYPE + " TEXT, " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + HISTORY_COL_LAT + " double, " +HISTORY_COL_LON + " double);"; //$NON-NLS-1$ //$NON-NLS-2$ + + + public HistoryItemDBHelper() { + } + + private SQLiteConnection openConnection(boolean readonly) { + SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); + if (conn.getVersion() == 0 || DB_VERSION != conn.getVersion()) { + if (readonly) { + conn.close(); + conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly); + } + if (conn.getVersion() == 0) { + conn.setVersion(DB_VERSION); + onCreate(conn); + } else { + onUpgrade(conn, conn.getVersion(), DB_VERSION); + } + + } + return conn; + } + + public void onCreate(SQLiteConnection db) { + db.execSQL(HISTORY_TABLE_CREATE); + } + + public void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { + } + + public boolean remove(HistoryEntry e){ + SQLiteConnection db = openConnection(false); + if(db != null){ + try { + db.execSQL("DELETE FROM " + HISTORY_TABLE_NAME + " WHERE " + HISTORY_COL_NAME + " = ?", new Object[] { e.getName() }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean removeAll(){ + SQLiteConnection db = openConnection(false); + if(db != null){ + try { + db.execSQL("DELETE FROM " + HISTORY_TABLE_NAME); //$NON-NLS-1$ + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean update(HistoryEntry e){ + SQLiteConnection db = openConnection(false); + if(db != null){ + try { + db.execSQL( + "UPDATE " + HISTORY_TABLE_NAME + " SET time = ? WHERE " + HISTORY_COL_NAME + " = ?", new Object[] { System.currentTimeMillis(), e.getName() }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean add(HistoryEntry e){ + SQLiteConnection db = openConnection(false); + if(db != null){ + try { + db.execSQL( + "INSERT INTO " + HISTORY_TABLE_NAME + " VALUES (?, ?, ?, ?, ?)", new Object[] { e.getName(), System.currentTimeMillis(), null, e.getLat(), e.getLon() }); //$NON-NLS-1$ //$NON-NLS-2$ + } finally { + db.close(); + } + return true; + } + return false; + } + + public List getEntries(){ + List entries = new ArrayList(); + SQLiteConnection db = openConnection(true); + if(db != null){ + try { + SQLiteCursor query = db.rawQuery( + "SELECT " + HISTORY_COL_NAME + ", " + HISTORY_COL_LAT + "," + HISTORY_COL_LON + " FROM " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + HISTORY_TABLE_NAME + " ORDER BY " + HISTORY_COL_TIME + " DESC", null); //$NON-NLS-1$//$NON-NLS-2$ + if (query.moveToFirst()) { + do { + HistoryEntry e = new HistoryEntry(query.getDouble(1), query.getDouble(2), query.getString(0)); + entries.add(e); + } while (query.moveToNext()); + } + query.close(); + } finally { + db.close(); + } + } + return entries; + } + + } + + + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/SpecialPhrases.java b/OsmAnd-java/src/net/osmand/plus/SpecialPhrases.java new file mode 100644 index 0000000000..de6836fc6f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/SpecialPhrases.java @@ -0,0 +1,100 @@ +package net.osmand.plus; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import net.osmand.PlatformUtil; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + + +public class SpecialPhrases { + + + private static Map m; + private static final Log log = PlatformUtil.getLog(SpecialPhrases.class); + + /** + * Use this method to query a special phrase for a certain subtype + * + * If the language isn't set yet, a nullpointer exception will be thrown + * + * @param value the subtype to query + * @return the special phrase according to the asked key, or "null" if the key isn't found + */ + public static String getSpecialPhrase(String value) { + if (m == null) { + // do not throw exception because OsmAndApplication is not always initiliazed before + // this call + log.warn("The language has not been set for special phrases"); + return value; + + } + String specialValue = m.get(value); + if(Algorithms.isEmpty(specialValue)) { + return value.replace('_', ' '); + } + return specialValue; + } + + /** + * Set the special phrases to a certain language. + * This method needs to be used before the getSpecialPhrase method + * + * @param lang the language to use + * @throws IOException when reading the text file failed + */ + public static void setLanguage(ClientContext ctx, OsmandSettings settings) throws IOException { + String lang = getPreferredLanguage(settings).getLanguage(); + m = new HashMap(); + // The InputStream opens the resourceId and sends it to the buffer + InputStream is = null; + BufferedReader br = null; + try { + try { + is = ctx.getInternalAPI().openAsset("specialphrases/specialphrases_" + lang + ".txt"); + } catch (IOException ex) { + // second try: default to English, if this fails, the error is thrown outside + is = ctx.getInternalAPI().openAsset("specialphrases/specialphrases_en.txt"); + } + br = new BufferedReader(new InputStreamReader(is)); + String readLine = null; + + // While the BufferedReader readLine is not null + while ((readLine = br.readLine()) != null) { + String[] arr = readLine.split(","); + if (arr != null && arr.length == 2) { + m.put(arr[0], arr[1]); + } + + } + + } finally { + Algorithms.closeStream(is); + Algorithms.closeStream(br); + } + + } + + /** + * Returns the preferred language + * @param set the OsmandSettings used + * @return ENGLISH if English names are chosen in the settings, Locale.getDefault otherwise + */ + public static Locale getPreferredLanguage(OsmandSettings set){ + if (set.usingEnglishNames()) { + return Locale.ENGLISH; + } + return Locale.getDefault(); + + } + + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/TargetPointsHelper.java b/OsmAnd-java/src/net/osmand/plus/TargetPointsHelper.java new file mode 100644 index 0000000000..5e05aea399 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/TargetPointsHelper.java @@ -0,0 +1,197 @@ +package net.osmand.plus; + + +import java.util.ArrayList; +import java.util.List; + +import net.osmand.Location; +import net.osmand.StateChangedListener; +import net.osmand.data.LatLon; +import net.osmand.plus.routing.RoutingHelper; + +public class TargetPointsHelper { + + private List intermediatePoints = new ArrayList(); + private List intermediatePointNames = new ArrayList(); + private LatLon pointToNavigate = null; + private OsmandSettings settings; + private RoutingHelper routingHelper; + private ClientContext ctx; + private List> listeners = new ArrayList>(); + + public TargetPointsHelper(ClientContext ctx){ + this.ctx = ctx; + this.settings = ctx.getSettings(); + this.routingHelper = ctx.getRoutingHelper(); + readFromSettings(settings); + } + + private void readFromSettings(OsmandSettings settings) { + pointToNavigate = settings.getPointToNavigate(); + intermediatePoints.clear(); + intermediatePointNames.clear(); + intermediatePoints.addAll(settings.getIntermediatePoints()); + intermediatePointNames.addAll(settings.getIntermediatePointDescriptions(intermediatePoints.size())); + } + + public LatLon getPointToNavigate() { + return pointToNavigate; + } + + public String getPointNavigateDescription(){ + return settings.getPointNavigateDescription(); + } + + public List getIntermediatePointNames() { + return intermediatePointNames; + } + + public List getIntermediatePoints() { + return intermediatePoints; + } + + public List getIntermediatePointsWithTarget() { + List res = new ArrayList(); + res.addAll(intermediatePoints); + if(pointToNavigate != null) { + res.add(pointToNavigate); + } + return res; + } + + public List getIntermediatePointNamesWithTarget() { + List res = new ArrayList(); + res.addAll(intermediatePointNames); + if(pointToNavigate != null) { + res.add(getPointNavigateDescription()); + } + return res; + } + + public LatLon getFirstIntermediatePoint(){ + if(intermediatePoints.size() > 0) { + return intermediatePoints.get(0); + } + return null; + } + + /** + * Clear the local and persistent waypoints list and destination. + */ + public void removeAllWayPoints(boolean updateRoute){ + settings.clearPointToNavigate(); + pointToNavigate = null; + settings.clearIntermediatePoints(); + settings.clearPointToNavigate(); + intermediatePoints.clear(); + intermediatePointNames.clear(); + updateRouteAndReferesh(updateRoute); + } + + /** + * Move an intermediate waypoint to the destination. + */ + public void makeWayPointDestination(boolean updateRoute, int index){ + pointToNavigate = intermediatePoints.remove(index); + settings.setPointToNavigate(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), + intermediatePointNames.remove(index)); + settings.deleteIntermediatePoint(index); + updateRouteAndReferesh(updateRoute); + } + + public void removeWayPoint(boolean updateRoute, int index){ + if(index < 0){ + settings.clearPointToNavigate(); + pointToNavigate = null; + int sz = intermediatePoints.size(); + if(sz > 0) { + settings.deleteIntermediatePoint(sz- 1); + pointToNavigate = intermediatePoints.remove(sz - 1); + settings.setPointToNavigate(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), + intermediatePointNames.remove(sz - 1)); + } + } else { + settings.deleteIntermediatePoint(index); + intermediatePoints.remove(index); + intermediatePointNames.remove(index); + } + updateRouteAndReferesh(updateRoute); + } + + private void updateRouteAndReferesh(boolean updateRoute) { + if(updateRoute && ( routingHelper.isRouteBeingCalculated() || routingHelper.isRouteCalculated() || + routingHelper.isFollowingMode())) { + Location lastKnownLocation = ctx.getLastKnownLocation(); + routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(), + settings.getIntermediatePoints(), lastKnownLocation, routingHelper.getCurrentGPXRoute()); + } + updateListeners(); + } + + public void addListener(StateChangedListener l) { + listeners.add(l); + } + + + private void updateListeners() { + for(StateChangedListener l : listeners) { + l.stateChanged(null); + } + } + + public void clearPointToNavigate(boolean updateRoute) { + settings.clearPointToNavigate(); + settings.clearIntermediatePoints(); + readFromSettings(settings); + updateRouteAndReferesh(updateRoute); + } + + + public void reorderAllTargetPoints(List point, + List names, boolean updateRoute){ + settings.clearPointToNavigate(); + if (point.size() > 0) { + settings.saveIntermediatePoints(point.subList(0, point.size() - 1), names.subList(0, point.size() - 1)); + LatLon p = point.get(point.size() - 1); + String nm = names.get(point.size() - 1); + settings.setPointToNavigate(p.getLatitude(), p.getLongitude(), nm); + } else { + settings.clearIntermediatePoints(); + } + readFromSettings(settings); + updateRouteAndReferesh(updateRoute); + } + + public void navigateToPoint(LatLon point, boolean updateRoute, int intermediate){ + if(point != null){ + if(intermediate < 0) { + settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null); + } else { + settings.insertIntermediatePoint(point.getLatitude(), point.getLongitude(), null, + intermediate, false); + } + } else { + settings.clearPointToNavigate(); + settings.clearIntermediatePoints(); + } + readFromSettings(settings); + updateRouteAndReferesh(updateRoute); + + } + + public boolean checkPointToNavigate(ClientContext ctx ){ + if(pointToNavigate == null){ + ctx.showToastMessage(R.string.mark_final_location_first); + return false; + } + return true; + } + + + + public void updatePointsFromSettings() { + readFromSettings(settings); + } + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/Version.java b/OsmAnd-java/src/net/osmand/plus/Version.java new file mode 100644 index 0000000000..aee72e682f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/Version.java @@ -0,0 +1,98 @@ +package net.osmand.plus; + + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +public class Version { + + private final String appVersion; + private final String appName; + private final static String FREE_VERSION_NAME = "net.osmand"; + + + public static boolean isGpsStatusEnabled(ClientContext ctx) { + return ctx.getString(R.string.versionFeatures).contains("+gps_status"); + } + + public static boolean isBlackberry(ClientContext ctx) { + return ctx.getString(R.string.versionFeatures).contains("+blackberry"); + } + + public static boolean isGooglePlayEnabled(ClientContext ctx) { + return ctx.getString(R.string.versionFeatures).contains("+play_market"); + } + + public static boolean isFreeVersionEnabled(ClientContext ctx) { + return ctx.getString(R.string.versionFeatures).contains("+free_version"); + } + + public static boolean isParkingPluginInlined(ClientContext ctx) { + return ctx.getString(R.string.versionFeatures).contains("+parking_plugin"); + } + + private Version(ClientContext ctx) { + appVersion = ctx.getString(R.string.app_version); + appName = ctx.getString(R.string.app_name); + } + + private static Version ver = null; + private static Version getVersion(ClientContext ctx){ + if(ver == null){ + ver = new Version(ctx); + } + return ver; + } + + public static String getFullVersion(ClientContext ctx){ + Version v = getVersion(ctx); + return v.appName + " " + v.appVersion; + } + + public static String getAppVersion(ClientContext ctx){ + Version v = getVersion(ctx); + return v.appVersion; + } + + public static String getAppName(ClientContext ctx){ + Version v = getVersion(ctx); + return v.appName; + } + + public static boolean isProductionVersion(ClientContext ctx){ + Version v = getVersion(ctx); + return !v.appVersion.contains("#"); + } + + public static String getVersionAsURLParam(ClientContext ctx) { + try { + return "osmandver=" + URLEncoder.encode(getVersionForTracker(ctx), "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e); + } + } + + public static boolean isFreeVersion(ClientContext ctx){ + return ctx.getInternalAPI().getPackageName().equals(FREE_VERSION_NAME) || isFreeVersionEnabled(ctx); + + } + + public static boolean isDeveloperVersion(ClientContext ctx){ + return "osmand~".equalsIgnoreCase(getAppName(ctx)); + + } + + public static String getVersionForTracker(ClientContext ctx) { + String v = Version.getAppName(ctx); + if(Version.isProductionVersion(ctx)){ + v = Version.getFullVersion(ctx); + } else { + v +=" test"; + } + return v; + } + + public static boolean isOldCoreVersion(ClientContext ctx) { + return ctx.getString(R.string.versionFeatures).contains("+oldCore"); + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/access/AccessibilityMode.java b/OsmAnd-java/src/net/osmand/plus/access/AccessibilityMode.java new file mode 100644 index 0000000000..f71179329f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/access/AccessibilityMode.java @@ -0,0 +1,22 @@ +package net.osmand.plus.access; + +import net.osmand.plus.ClientContext; +import net.osmand.plus.R; + +public enum AccessibilityMode { + + ON(R.string.accessibility_on), + OFF(R.string.accessibility_off), + DEFAULT(R.string.accessibility_default); + + private final int key; + + AccessibilityMode(int key) { + this.key = key; + } + + public String toHumanString(ClientContext ctx) { + return ctx.getString(key); + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/access/RelativeDirectionStyle.java b/OsmAnd-java/src/net/osmand/plus/access/RelativeDirectionStyle.java new file mode 100644 index 0000000000..f4f8849b6d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/access/RelativeDirectionStyle.java @@ -0,0 +1,21 @@ +package net.osmand.plus.access; + +import net.osmand.plus.ClientContext; +import net.osmand.plus.R; + +public enum RelativeDirectionStyle { + + SIDEWISE(R.string.direction_style_sidewise), + CLOCKWISE(R.string.direction_style_clockwise); + + private final int key; + + RelativeDirectionStyle(int key) { + this.key = key; + } + + public String toHumanString(ClientContext ctx) { + return ctx.getString(key); + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/ExternalServiceAPI.java b/OsmAnd-java/src/net/osmand/plus/api/ExternalServiceAPI.java new file mode 100644 index 0000000000..da7ac2b043 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/ExternalServiceAPI.java @@ -0,0 +1,24 @@ +package net.osmand.plus.api; + +import net.osmand.plus.ClientContext; + +public interface ExternalServiceAPI { + + public boolean isWifiConnected(); + + public boolean isInternetConnected(); + + + public boolean isLightSensorEnabled(); + + public String getExternalStorageDirectory(); + + public AudioFocusHelper getAudioFocuseHelper(); + + public interface AudioFocusHelper { + + public boolean requestFocus(ClientContext context, int streamType); + + public boolean abandonFocus(ClientContext context, int streamType); + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/InternalOsmAndAPI.java b/OsmAnd-java/src/net/osmand/plus/api/InternalOsmAndAPI.java new file mode 100644 index 0000000000..698c657753 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/InternalOsmAndAPI.java @@ -0,0 +1,61 @@ +package net.osmand.plus.api; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import net.osmand.NativeLibrary; +import net.osmand.ResultMatcher; +import net.osmand.data.Amenity; +import net.osmand.plus.PoiFilter; +import net.osmand.plus.TargetPointsHelper; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlSerializer; + +public interface InternalOsmAndAPI { + + public XmlSerializer newSerializer(); + + public XmlPullParser newPullParser(); + + public String getPackageName(); + + public String getVersionName(); + + public int getVersionCode(); + + public InputStream openAsset(String name) throws IOException; + + public NativeLibrary getNativeLibrary(); + + public boolean accessibilityEnabled(); + + public boolean accessibilityExtensions(); + + public List searchAmenities(PoiFilter filter, + double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, + double lat, double lon, ResultMatcher matcher); + + public List searchAmenitiesByName(String searchQuery, + double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, + double lat, double lon, ResultMatcher matcher); + + public String getDeviceName(); + + public String getBrandName(); + + public String getModelName(); + + public TargetPointsHelper getTargetPointsHelper(); + + public boolean isNavigationServiceStarted(); + + public boolean isNavigationServiceStartedForNavigation(); + + public void startNavigationService(boolean forNavigation); + + public void stopNavigationService(); + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/InternalToDoAPI.java b/OsmAnd-java/src/net/osmand/plus/api/InternalToDoAPI.java new file mode 100644 index 0000000000..21b1f3a186 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/InternalToDoAPI.java @@ -0,0 +1,17 @@ +package net.osmand.plus.api; + +import java.io.File; +import java.util.List; + +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.map.ITileSource; +import net.osmand.map.TileSourceManager.TileSourceTemplate; + +public interface InternalToDoAPI { + + public BinaryMapIndexReader[] getRoutingMapFiles(); + + public ITileSource newSqliteTileSource(File dir, List knownTemplates); + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/RendererAPI.java b/OsmAnd-java/src/net/osmand/plus/api/RendererAPI.java new file mode 100644 index 0000000000..f95f15fa9c --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/RendererAPI.java @@ -0,0 +1,9 @@ +package net.osmand.plus.api; + +import net.osmand.plus.api.render.Paint; + +public interface RendererAPI { + + public Paint newPaint(); + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/SQLiteAPI.java b/OsmAnd-java/src/net/osmand/plus/api/SQLiteAPI.java new file mode 100644 index 0000000000..1d6c599b6c --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/SQLiteAPI.java @@ -0,0 +1,81 @@ +package net.osmand.plus.api; + + + +public interface SQLiteAPI { + + public interface SQLiteConnection { + + void close(); + + SQLiteCursor rawQuery(String sql, String[] selectionArgs); + + void execSQL(String query); + + void execSQL(String query, Object[] objects); + + SQLiteStatement compileStatement(String string); + + void setVersion(int newVersion); + + int getVersion(); + + boolean isReadOnly(); + + boolean isDbLockedByOtherThreads(); + + boolean isClosed(); + + } + + public interface SQLiteCursor { + + boolean moveToFirst(); + + boolean moveToNext(); + + /** + * Takes parameter value (zero based) + */ + String getString(int ind); + + double getDouble(int ind); + + long getLong(int ind); + + long getInt(int ind); + + byte[] getBlob(int ind); + + void close(); + + + + } + + public interface SQLiteStatement { + + // 1 based argument + void bindString(int i, String filterId); + + // 1 based argument + void bindNull(int i); + + void execute(); + + void close(); + + long simpleQueryForLong(); + + String simpleQueryForString(); + + void bindLong(int i, long val); + + void bindBlob(int i, byte[] val); + + } + + public SQLiteConnection getOrCreateDatabase(String name, boolean readOnly); + + public SQLiteConnection openByAbsolutePath(String path, boolean readOnly); +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/SettingsAPI.java b/OsmAnd-java/src/net/osmand/plus/api/SettingsAPI.java new file mode 100644 index 0000000000..54267c3c5c --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/SettingsAPI.java @@ -0,0 +1,33 @@ +package net.osmand.plus.api; + +public interface SettingsAPI { + + // world readable + public Object getPreferenceObject(String key); + + public interface SettingsEditor { + + public SettingsEditor putString(String key, String value); + public SettingsEditor putBoolean(String key, boolean value); + public SettingsEditor putFloat(String key, float value); + public SettingsEditor putInt(String key, int value); + public SettingsEditor putLong(String key, long value); + public SettingsEditor remove(String key); + public boolean commit(); + } + + public SettingsEditor edit(Object pref); + + public String getString(Object pref, String key, String defValue); + + public float getFloat(Object pref, String key, float defValue); + + public boolean getBoolean(Object pref, String key, boolean defValue); + + public int getInt(Object pref, String key, int defValue); + + public long getLong(Object pref, String key, long defValue); + + public boolean contains(Object pref, String key); + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/render/Canvas.java b/OsmAnd-java/src/net/osmand/plus/api/render/Canvas.java new file mode 100644 index 0000000000..e767e66c61 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/render/Canvas.java @@ -0,0 +1,5 @@ +package net.osmand.plus.api.render; + +public interface Canvas { + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/render/Color.java b/OsmAnd-java/src/net/osmand/plus/api/render/Color.java new file mode 100644 index 0000000000..5df8aad7fc --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/render/Color.java @@ -0,0 +1,24 @@ +package net.osmand.plus.api.render; + +public class Color { + public static final int BLACK = 0xFF000000; + public static final int DKGRAY = 0xFF444444; + public static final int GRAY = 0xFF888888; + public static final int LTGRAY = 0xFFCCCCCC; + public static final int WHITE = 0xFFFFFFFF; + public static final int RED = 0xFFFF0000; + public static final int GREEN = 0xFF00FF00; + public static final int BLUE = 0xFF0000FF; + public static final int YELLOW = 0xFFFFFF00; + public static final int CYAN = 0xFF00FFFF; + public static final int MAGENTA = 0xFFFF00FF; + public static final int TRANSPARENT = 0; + + public static int rgb(int red, int green, int blue) { + return (0xFF << 24) | (red << 16) | (green << 8) | blue; + } + + public static int argb(int alpha, int red, int green, int blue) { + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/render/Paint.java b/OsmAnd-java/src/net/osmand/plus/api/render/Paint.java new file mode 100644 index 0000000000..018ac9ab3e --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/render/Paint.java @@ -0,0 +1,56 @@ +package net.osmand.plus.api.render; + + +public interface Paint { + public enum Style { + FILL (0), + STROKE (1), + FILL_AND_STROKE (2); + Style(int nativeInt) { + this.nativeInt = nativeInt; + } + final int nativeInt; + } + + public enum Cap { + BUTT (0), + ROUND (1), + SQUARE (2); + private Cap(int nativeInt) { + this.nativeInt = nativeInt; + } + final int nativeInt; + } + + public enum Join { + MITER (0), + ROUND (1), + BEVEL (2); + private Join(int nativeInt) { + this.nativeInt = nativeInt; + } + final int nativeInt; + } + + public enum Align { + LEFT (0), + CENTER (1), + RIGHT (2); + private Align(int nativeInt) { + this.nativeInt = nativeInt; + } + final int nativeInt; + } + + void setColor(int color); + + int getColor(); + + void setTextAlign(Align align); + + void setStrokeWidth(float width); + + void setAntiAlias(boolean flag); + + void setStyle(Style style); +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/render/Path.java b/OsmAnd-java/src/net/osmand/plus/api/render/Path.java new file mode 100644 index 0000000000..0a384baf05 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/render/Path.java @@ -0,0 +1,5 @@ +package net.osmand.plus.api.render; + +public interface Path { + +} diff --git a/OsmAnd-java/src/net/osmand/plus/api/render/Typeface.java b/OsmAnd-java/src/net/osmand/plus/api/render/Typeface.java new file mode 100644 index 0000000000..a234efd27b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/api/render/Typeface.java @@ -0,0 +1,5 @@ +package net.osmand.plus.api.render; + +public class Typeface { + +} diff --git a/OsmAnd-java/src/net/osmand/plus/download/DownloadActivityType.java b/OsmAnd-java/src/net/osmand/plus/download/DownloadActivityType.java new file mode 100644 index 0000000000..af145dcc09 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/DownloadActivityType.java @@ -0,0 +1,5 @@ +package net.osmand.plus.download; + +public enum DownloadActivityType { + NORMAL_FILE, ROADS_FILE, SRTM_FILE, HILLSHADE_FILE +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/download/DownloadEntry.java b/OsmAnd-java/src/net/osmand/plus/download/DownloadEntry.java new file mode 100644 index 0000000000..cbbea40b88 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/DownloadEntry.java @@ -0,0 +1,33 @@ +package net.osmand.plus.download; + +import java.io.File; +import java.util.List; + +public class DownloadEntry { + public File fileToSave; + public File fileToUnzip; + public boolean unzip; + public Long dateModified; + public double sizeMB; + public String baseName; + public String urlToDownload; + public int parts; + public File existingBackupFile; + public boolean isAsset; + public DownloadActivityType type; + + public List srtmFilesToDownload; + public DownloadEntry attachedEntry; + + public DownloadEntry() { + // default + } + + public DownloadEntry(String assetName, String fileName, long dateModified) { + this.dateModified = dateModified; + fileToUnzip = new File(fileName); + fileToSave = new File(assetName); + isAsset = true; + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/download/DownloadFileHelper.java b/OsmAnd-java/src/net/osmand/plus/download/DownloadFileHelper.java new file mode 100644 index 0000000000..5de4bbb7f1 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/DownloadFileHelper.java @@ -0,0 +1,320 @@ +package net.osmand.plus.download; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import net.osmand.IProgress; +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.plus.ClientContext; +import net.osmand.plus.R; +import net.osmand.plus.Version; + +import org.apache.commons.logging.Log; + +public class DownloadFileHelper { + + private final static Log log = PlatformUtil.getLog(DownloadFileHelper.class); + private static final int BUFFER_SIZE = 32256; + protected final int TRIES_TO_DOWNLOAD = 15; + protected final long TIMEOUT_BETWEEN_DOWNLOADS = 8000; + private final ClientContext ctx; + private boolean interruptDownloading = false; + + + public DownloadFileHelper(ClientContext ctx){ + this.ctx = ctx; + } + + public interface DownloadFileShowWarning { + + public void showWarning(String warning); + } + + private void downloadFileInternal(String fileName, FileOutputStream out, URL url, String part, String indexOfAllFiles, + IProgress progress, boolean forceWifi) throws IOException, InterruptedException { + InputStream is = null; + byte[] buffer = new byte[BUFFER_SIZE]; + int read = 0; + int length = 0; + int fileread = 0; + int triesDownload = TRIES_TO_DOWNLOAD; + boolean notFound = false; + boolean first = true; + try { + while (triesDownload > 0) { + try { + if (!first) { + log.info("Reconnecting"); //$NON-NLS-1$ + try { + Thread.sleep(TIMEOUT_BETWEEN_DOWNLOADS); + } catch (InterruptedException e) { + } + } + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("User-Agent", Version.getFullVersion(ctx)); //$NON-NLS-1$ + conn.setReadTimeout(30000); + if (fileread > 0) { + String range = "bytes="+fileread + "-" + (length -1); //$NON-NLS-1$ //$NON-NLS-2$ + conn.setRequestProperty("Range", range); //$NON-NLS-1$ + } + conn.setConnectTimeout(30000); + log.info(conn.getResponseMessage() + " " + conn.getResponseCode()); //$NON-NLS-1$ + boolean wifiConnectionBroken = forceWifi && !isWifiConnected(); + if(conn.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND){ + notFound = true; + break; + } + if ((conn.getResponseCode() != HttpURLConnection.HTTP_PARTIAL && + conn.getResponseCode() != HttpURLConnection.HTTP_OK ) || wifiConnectionBroken) { + conn.disconnect(); + triesDownload--; + continue; + } + is = conn.getInputStream(); + if (first) { + length = conn.getContentLength(); + String taskName = ctx.getString(R.string.downloading_file) + indexOfAllFiles +" " + fileName; + if(part != null){ + taskName += part; + } + progress.startTask(taskName, length / 1024); //$NON-NLS-1$ + } + + first = false; + while ((read = is.read(buffer)) != -1) { + if(interruptDownloading){ + throw new InterruptedException(); + } + out.write(buffer, 0, read); + fileread += read; + progress.remaining((length - fileread) / 1024); + } + if(length <= fileread){ + triesDownload = 0; + } + } catch (IOException e) { + log.error("IOException", e); //$NON-NLS-1$ + triesDownload--; + } + + } + } finally { + if (is != null) { + is.close(); + } + } + if(notFound) { + throw new IOException("File not found " + fileName); //$NON-NLS-1$ + } else if(length != fileread || length == 0){ + throw new IOException("File was not fully read"); //$NON-NLS-1$ + } + + } + + public boolean isWifiConnected(){ + return ctx.getExternalServiceAPI().isWifiConnected(); + } + + public boolean downloadFile(DownloadEntry de, IProgress progress, + List toReIndex, String indexOfAllFiles, + DownloadFileShowWarning showWarningCallback, boolean forceWifi) throws InterruptedException { + try { + FileOutputStream out = new FileOutputStream(de.fileToSave); + try { + + if (de.parts == 1) { + URL url = new URL(de.urlToDownload); //$NON-NLS-1$ + log.info("Download " + de.urlToDownload); + downloadFileInternal(de.baseName, out, url, null, indexOfAllFiles, progress, forceWifi); + } else { + for (int i = 1; i <= de.parts; i++) { + URL url = new URL(de.urlToDownload + "-" + i); //$NON-NLS-1$ + log.info("Download " + de.urlToDownload + "-" + i); + downloadFileInternal(de.baseName, out, url, " [" + i + "/" + de.parts + "]", indexOfAllFiles, progress, forceWifi); + } + } + } finally { + out.close(); + } + unzipFile(de, progress, toReIndex); + showWarningCallback.showWarning(ctx.getString(R.string.download_index_success)); + return true; + } catch (IOException e) { + log.error("Exception ocurred", e); //$NON-NLS-1$ + showWarningCallback.showWarning(ctx.getString(R.string.error_io_error) + " : " + e.getMessage()); + // Possibly file is corrupted + de.fileToSave.delete(); + return false; + } catch (InterruptedException e) { + // Possibly file is corrupted + de.fileToSave.delete(); + throw e; + } + } + + private void unzipFile(DownloadEntry de, IProgress progress, List toReIndex) + throws FileNotFoundException, IOException { + if (de.fileToSave.getName().endsWith(".zip")) { //$NON-NLS-1$ + if (de.unzip) { + de.fileToUnzip.mkdirs(); + } + CountingInputStream fin = new CountingInputStream(new FileInputStream(de.fileToSave)); + ZipInputStream zipIn = new ZipInputStream(fin); + ZipEntry entry = null; + boolean first = true; + int len = (int) de.fileToSave.length(); + progress.startTask(ctx.getString(R.string.unzipping_file), len / 1024); + while ((entry = zipIn.getNextEntry()) != null) { + if (entry.isDirectory() || entry.getName().endsWith(IndexConstants.GEN_LOG_EXT)) { + continue; + } + File fs; + if (!de.unzip) { + if (first) { + fs = de.fileToUnzip; + first = false; + } else { + String name = entry.getName(); + // small simplification + int ind = name.lastIndexOf('_'); + if (ind > 0) { + // cut version + int i = name.indexOf('.', ind); + if (i > 0) { + name = name.substring(0, ind) + name.substring(i, name.length()); + } + } + fs = new File(de.fileToUnzip.getParent(), name); + } + } else { + fs = new File(de.fileToUnzip, entry.getName()); + } + FileOutputStream out = new FileOutputStream(fs); + int read; + byte[] buffer = new byte[BUFFER_SIZE]; + int remaining = len; + while ((read = zipIn.read(buffer)) != -1) { + out.write(buffer, 0, read); + remaining -= fin.lastReadCount(); + progress.remaining(remaining / 1024); + } + out.close(); + + if (de.dateModified != null) { + fs.setLastModified(de.dateModified); + } + toReIndex.add(fs); + } + zipIn.close(); + de.fileToSave.delete(); // zip is no needed more + } + } + + + public void setInterruptDownloading(boolean interruptDownloading) { + this.interruptDownloading = interruptDownloading; + } + + public boolean isInterruptDownloading() { + return interruptDownloading; + } + + private static class CountingInputStream extends InputStream { + + private final InputStream delegate; + private int count; + + public CountingInputStream(InputStream delegate) { + this.delegate = delegate; + } + + public int lastReadCount() { + int last = count; + count = 0; + return last; + } + + @Override + public int available() throws IOException { + return delegate.available(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public void mark(int readlimit) { + delegate.mark(readlimit); + } + + @Override + public boolean markSupported() { + return delegate.markSupported(); + } + + @Override + public int read() throws IOException { + int read = delegate.read(); + if (read > 0) { + this.count++;; + } + return read; + } + + @Override + public int read(byte[] buffer, int offset, int length) + throws IOException { + int read = delegate.read(buffer, offset, length); + if (read > 0) { + this.count += read; + } + return read; + } + + @Override + public int read(byte[] buffer) throws IOException { + int read = delegate.read(buffer); + if (read > 0) { + this.count += read; + } + return read; + } + + @Override + public void reset() throws IOException { + delegate.reset(); + } + + @Override + public long skip(long byteCount) throws IOException { + return delegate.skip(byteCount); + } + + @Override + public String toString() { + return delegate.toString(); + } + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/download/DownloadTracker.java b/OsmAnd-java/src/net/osmand/plus/download/DownloadTracker.java new file mode 100644 index 0000000000..e21529c5e5 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/DownloadTracker.java @@ -0,0 +1,110 @@ +package net.osmand.plus.download; + +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; + +import net.osmand.PlatformUtil; +import net.osmand.plus.ClientContext; +import net.osmand.plus.Version; + +import org.apache.commons.logging.Log; + +public class DownloadTracker { + private static final Log log = PlatformUtil.getLog(DownloadTracker.class); + + private Map getCustomVars(ClientContext ctx) { + Map map = new LinkedHashMap(); + map.put("App", Version.getFullVersion(ctx)); + map.put("Device", ctx.getInternalAPI().getDeviceName()); + map.put("Brand", ctx.getInternalAPI().getBrandName()); + map.put("Model", ctx.getInternalAPI().getModelName()); + map.put("Package", ctx.getInternalAPI().getPackageName()); + + map.put("Version name", ctx.getInternalAPI().getVersionName()); + map.put("Version code", ctx.getInternalAPI().getVersionCode()+""); + return map; + } + + private String randomNumber() { + return (new Random(System.currentTimeMillis()).nextInt(100000000) + 100000000) + ""; + } + + final String beaconUrl = "http://www.google-analytics.com/__utm.gif"; + final String analyticsVersion = "4.3"; // Analytics version - AnalyticsVersion + + public void trackEvent(ClientContext a, + String category, String action, String label, int value, String trackingAcount) { + Map parameters = new LinkedHashMap(); + try { + Map customVariables = getCustomVars(a); + parameters.put("AnalyticsVersion", analyticsVersion); + parameters.put("utmn", randomNumber()); + parameters.put("utmhn", "http://app.osmand.net"); + parameters.put("utmni", "1"); + parameters.put("utmt", "event"); + + StringBuilder customVars = new StringBuilder(); + Iterator> customs = customVariables.entrySet().iterator(); + for (int i = 0; i < customVariables.size(); i++) { + Entry n = customs.next(); + if (i > 0) { + customVars.append("*"); + } + // "'" => "'0", ')' => "'1", '*' => "'2", '!' => "'3", + customVars.append((i + 1) + "!").append((n.getKey() + n.getValue())); + } + + parameters.put("utmcs", "UTF-8"); + parameters.put("utmul", "en"); + parameters.put("utmhid", (System.currentTimeMillis() / 1000) + ""); + parameters.put("utmac", trackingAcount); + String domainHash = "app.osmand.net".hashCode() + ""; + + String utma = domainHash + "."; + File fl = a.getAppPath(".nomedia"); + if (fl.exists()) { + utma += (fl.lastModified()) + "."; + } else { + utma += (randomNumber()) + "."; + } + utma += ((System.currentTimeMillis() / 1000) + "."); + utma += ((System.currentTimeMillis() / 1000) + "."); + utma += ((System.currentTimeMillis() / 1000) + "."); + utma += "1"; + parameters.put("utmcc", "__utma=" + utma + ";"); + parameters.put("utme", MessageFormat.format("5({0}*{1}*{2})({3})", category, action, label == null ? "" : label, value) + + customVars); + + StringBuilder urlString = new StringBuilder(beaconUrl + "?"); + Iterator> it = parameters.entrySet().iterator(); + while (it.hasNext()) { + Entry e = it.next(); + urlString.append(e.getKey()).append("=").append(URLEncoder.encode(e.getValue(), "UTF-8")); + if (it.hasNext()) { + urlString.append("&"); + } + } + + log.debug(urlString); + URL url = new URL(urlString.toString()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setConnectTimeout(5000); + conn.setDoInput(false); + conn.setDoOutput(false); + conn.connect(); + log.info("Response analytics is " + conn.getResponseCode() + " " + conn.getResponseMessage()); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/download/IndexFileList.java b/OsmAnd-java/src/net/osmand/plus/download/IndexFileList.java new file mode 100644 index 0000000000..5086dda169 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/IndexFileList.java @@ -0,0 +1,92 @@ +package net.osmand.plus.download; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.osmand.IndexConstants; + +public class IndexFileList implements Serializable { + private static final long serialVersionUID = 1L; + + private boolean downloadedFromInternet = false; + IndexItem basemap; + ArrayList indexFiles = new ArrayList(); + private String mapversion; + + private Comparator comparator = new Comparator(){ + @Override + public int compare(IndexItem o1, IndexItem o2) { + String object1 = o1.getFileName(); + String object2 = o2.getFileName(); + if(object1.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){ + if(object2.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){ + return object1.compareTo(object2); + } else { + return -1; + } + } else if(object2.endsWith(IndexConstants.ANYVOICE_INDEX_EXT_ZIP)){ + return 1; + } + return object1.compareTo(object2); + } + }; + + public void setDownloadedFromInternet(boolean downloadedFromInternet) { + this.downloadedFromInternet = downloadedFromInternet; + } + + public boolean isDownloadedFromInternet() { + return downloadedFromInternet; + } + + public void setMapVersion(String mapversion) { + this.mapversion = mapversion; + } + + public void add(IndexItem indexItem) { + if (indexItem.isAccepted()) { + indexFiles.add(indexItem); + } + if(indexItem.getFileName().toLowerCase().startsWith("world_basemap")) { + basemap = indexItem; + } + } + + public void sort(){ + Collections.sort(indexFiles, comparator); + } + + public boolean isAcceptable() { + return (indexFiles != null && !indexFiles.isEmpty()) || (mapversion != null); + } + + public List getIndexFiles() { + return indexFiles; + } + + public IndexItem getBasemap() { + return basemap; + } + + public boolean isIncreasedMapVersion() { + try { + int mapVersionInList = Integer.parseInt(mapversion); + return IndexConstants.BINARY_MAP_VERSION < mapVersionInList; + } catch (NumberFormatException e) { + //ignore this... + } + return false; + } + + public IndexItem getIndexFilesByName(String key) { + for(IndexItem i : indexFiles) { + if(i.getFileName().equals(key)) { + return i; + } + } + return null; + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/download/IndexItem.java b/OsmAnd-java/src/net/osmand/plus/download/IndexItem.java new file mode 100644 index 0000000000..55bb5ff507 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/IndexItem.java @@ -0,0 +1,272 @@ +package net.osmand.plus.download; + +import static net.osmand.IndexConstants.BINARY_MAP_INDEX_EXT; +import static net.osmand.IndexConstants.BINARY_MAP_INDEX_EXT_ZIP; +import static net.osmand.IndexConstants.TTSVOICE_INDEX_EXT_ZIP; +import static net.osmand.IndexConstants.VOICE_INDEX_EXT_ZIP; + +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.plus.ClientContext; +import net.osmand.plus.R; +import net.osmand.plus.Version; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; + +public class IndexItem implements Comparable { + private static final Log log = PlatformUtil.getLog(IndexItem.class); + + String description; + String date; + String parts; + String fileName; + String size; + IndexItem attachedItem; + DownloadActivityType type; + + public IndexItem(String fileName, String description, String date, String size, String parts) { + this.fileName = fileName; + this.description = description; + this.date = date; + this.size = size; + this.parts = parts; + this.type = DownloadActivityType.NORMAL_FILE; + } + + public DownloadActivityType getType() { + return type; + } + + public void setType(DownloadActivityType type) { + this.type = type; + } + + public String getVisibleDescription(ClientContext ctx) { + String s = ""; //$NON-NLS-1$ + if (type == DownloadActivityType.SRTM_FILE) { + return ctx.getString(R.string.download_srtm_maps); + } else if (type == DownloadActivityType.ROADS_FILE) { + return ctx.getString(R.string.download_roads_only_item); + } + if (fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT) || fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP)) { + } else if (fileName.endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP)) { + s = ctx.getString(R.string.voice); + } else if (fileName.endsWith(IndexConstants.TTSVOICE_INDEX_EXT_ZIP)) { + s = ctx.getString(R.string.ttsvoice); + } + return s; + } + + public String getVisibleName(ClientContext ctx) { + return getBasename().replace('_', ' '); + } + + public String getBasename() { + if (fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)) { + return fileName.substring(0, fileName.length() - IndexConstants.EXTRA_ZIP_EXT.length()); + } + if (fileName.endsWith(IndexConstants.SQLITE_EXT)) { + return fileName.substring(0, fileName.length() - IndexConstants.SQLITE_EXT.length()).replace('_', ' '); + } + int ls = fileName.lastIndexOf('_'); + if (ls >= 0) { + return fileName.substring(0, ls); + } + return fileName; + } + + public boolean isAccepted() { + // POI index download is not supported any longer + if (fileName.endsWith(addVersionToExt(IndexConstants.BINARY_MAP_INDEX_EXT, IndexConstants.BINARY_MAP_VERSION)) // + || fileName.endsWith(addVersionToExt(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP, IndexConstants.BINARY_MAP_VERSION)) // + || fileName.endsWith(addVersionToExt(IndexConstants.VOICE_INDEX_EXT_ZIP, IndexConstants.VOICE_VERSION)) + || fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT) + || fileName.endsWith(IndexConstants.SQLITE_EXT) + // || fileName.endsWith(addVersionToExt(IndexConstants.TTSVOICE_INDEX_EXT_ZIP, IndexConstants.TTSVOICE_VERSION)) drop support for + // downloading tts files from inet + ) { + return true; + } + return false; + } + + protected static String addVersionToExt(String ext, int version) { + return "_" + version + ext; + } + + public String getFileName() { + return fileName; + } + + public String getDescription() { + return description; + } + + public String getDate() { + return date; + } + + public String getSizeDescription(ClientContext ctx) { + return size + " MB"; + } + + public String getSize() { + return size; + } + + public List createDownloadEntry(ClientContext ctx, DownloadActivityType type, + List downloadEntries) { + String fileName = this.fileName; + File parent = null; + String toSavePostfix = null; + String toCheckPostfix = null; + boolean unzipDir = false; + boolean preventMediaIndexing = false; + if (fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) { + parent = ctx.getAppPath(IndexConstants.MAPS_PATH); + toSavePostfix = BINARY_MAP_INDEX_EXT; + toCheckPostfix = BINARY_MAP_INDEX_EXT; + } else if (fileName.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP)) { + parent = ctx.getAppPath(IndexConstants.MAPS_PATH); + toSavePostfix = BINARY_MAP_INDEX_EXT_ZIP; + toCheckPostfix = BINARY_MAP_INDEX_EXT; + } else if (fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)) { + parent = ctx.getAppPath(""); + // unzipDir = true; + toSavePostfix = IndexConstants.EXTRA_ZIP_EXT; + toCheckPostfix = IndexConstants.EXTRA_EXT; + } else if (fileName.endsWith(IndexConstants.SQLITE_EXT)) { + parent = ctx.getAppPath(IndexConstants.TILES_INDEX_DIR); + toSavePostfix = IndexConstants.SQLITE_EXT; + toCheckPostfix = IndexConstants.SQLITE_EXT; + } else if (fileName.endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP)) { + parent = ctx.getAppPath(IndexConstants.VOICE_INDEX_DIR); + toSavePostfix = VOICE_INDEX_EXT_ZIP; + toCheckPostfix = ""; //$NON-NLS-1$ + unzipDir = true; + preventMediaIndexing = true; + } else if (fileName.endsWith(IndexConstants.TTSVOICE_INDEX_EXT_ZIP)) { + parent = ctx.getAppPath(IndexConstants.VOICE_INDEX_DIR); + toSavePostfix = TTSVOICE_INDEX_EXT_ZIP; + toCheckPostfix = ""; //$NON-NLS-1$ + unzipDir = true; + } + if (type == DownloadActivityType.ROADS_FILE) { + toSavePostfix = "-roads" + toSavePostfix; + toCheckPostfix = "-roads" + toCheckPostfix; + } + if (parent != null) { + parent.mkdirs(); + // ".nomedia" indicates there are no pictures and no music to list in this dir for the Gallery and Music apps + if (preventMediaIndexing) { + try { + new File(parent, ".nomedia").createNewFile();//$NON-NLS-1$ + } catch (IOException e) { + // swallow io exception + log.error("IOException", e); + } + } + } + final DownloadEntry entry; + if (parent == null || !parent.exists()) { + ctx.showToastMessage(R.string.sd_dir_not_accessible); + } else { + entry = new DownloadEntry(); + entry.type = type; + entry.baseName = getBasename(); + String url = "http://" + IndexConstants.INDEX_DOWNLOAD_DOMAIN + "/download?event=2&"; + url += Version.getVersionAsURLParam(ctx) + "&"; + if (type == DownloadActivityType.ROADS_FILE) { + url += "road=yes&"; + } + if (type == DownloadActivityType.HILLSHADE_FILE) { + url += "hillshade=yes&"; + } + entry.urlToDownload = url + "file=" + fileName; + entry.fileToSave = new File(parent, entry.baseName + toSavePostfix); + entry.unzip = unzipDir; + try { + Date d = Algorithms.getDateFormat().parse(date); + entry.dateModified = d.getTime(); + } catch (ParseException e1) { + log.error("ParseException", e1); + } + try { + entry.sizeMB = Double.parseDouble(size); + } catch (NumberFormatException e1) { + log.error("ParseException", e1); + } + entry.parts = 1; + if (parts != null) { + entry.parts = Integer.parseInt(parts); + } + entry.fileToUnzip = new File(parent, entry.baseName + toCheckPostfix); + File backup = new File(ctx.getAppPath(IndexConstants.BACKUP_INDEX_DIR), entry.fileToUnzip.getName()); + if (backup.exists()) { + entry.existingBackupFile = backup; + } + if (attachedItem != null) { + ArrayList sz = new ArrayList(); + attachedItem.createDownloadEntry(ctx, type, sz); + if(sz.size() > 0) { + entry.attachedEntry = sz.get(0); + } + } + downloadEntries.add(entry); + } + return downloadEntries; + } + + public String getTargetFileName(){ + String e = getFileName(); + + if (e.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT) || e.endsWith(IndexConstants.BINARY_MAP_INDEX_EXT_ZIP)) { + int l = e.lastIndexOf('_'); + if(l == -1) { + l = e.length(); + } + String s = e.substring(0, l); + if (getType() == DownloadActivityType.ROADS_FILE) { + s += "-roads" ; + } + s += IndexConstants.BINARY_MAP_INDEX_EXT; + return s; + } else if(e.endsWith(IndexConstants.SQLITE_EXT)){ + return e.replace('_', ' '); + } else if(e.endsWith(IndexConstants.EXTRA_ZIP_EXT)){ + return e.substring(0, e.length() - IndexConstants.EXTRA_ZIP_EXT.length()) + IndexConstants.EXTRA_EXT; + } else if(e.endsWith(IndexConstants.VOICE_INDEX_EXT_ZIP) || e.endsWith(IndexConstants.TTSVOICE_INDEX_EXT_ZIP)) { + int l = e.lastIndexOf('_'); + if(l == -1) { + l = e.length(); + } + String s = e.substring(0, l); + return s; + } + + return e; + } + + @Override + public int compareTo(IndexItem another) { + if(another == null) { + return -1; + } + return getFileName().compareTo(another.getFileName()); + } + + public boolean isAlreadyDownloaded(Map listAlreadyDownloaded) { + return listAlreadyDownloaded.containsKey(getTargetFileName()); + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/download/IndexItemCategory.java b/OsmAnd-java/src/net/osmand/plus/download/IndexItemCategory.java new file mode 100644 index 0000000000..2d3faf3aaa --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/IndexItemCategory.java @@ -0,0 +1,93 @@ +package net.osmand.plus.download; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import net.osmand.plus.ClientContext; +import net.osmand.plus.R; + +public class IndexItemCategory implements Comparable { + public final String name; + public final List items = new ArrayList(); + private final int order; + + public IndexItemCategory(String name, int order) { + this.name = name; + this.order = order; + } + + @Override + public int compareTo(IndexItemCategory another) { + return order < another.order ? -1 : 1; + } + + public static List categorizeIndexItems(ClientContext ctx, Collection indexItems) { + final Map cats = new TreeMap(); + for (IndexItem i : indexItems) { + int nameId = R.string.index_name_other; + int order = 0; + String lc = i.getFileName().toLowerCase(); + if (lc.endsWith(".voice.zip")) { + nameId = R.string.index_name_voice; + order = 1; + } else if (lc.contains(".ttsvoice.zip")) { + nameId = R.string.index_name_tts_voice; + order = 2; + } else if (lc.startsWith("us") || + (lc.contains("united states") && lc.startsWith("north-america")) ) { + nameId = R.string.index_name_us; + order = 31; + } else if (lc.contains("openmaps")) { + nameId = R.string.index_name_openmaps; + order = 10; + } else if (lc.contains("northamerica") || lc.contains("north-america")) { + nameId = R.string.index_name_north_america; + order = 30; + } else if (lc.contains("centralamerica") || lc.contains("central-america") + || lc.contains("caribbean")) { + nameId = R.string.index_name_central_america; + order = 40; + } else if (lc.contains("southamerica") || lc.contains("south-america")) { + nameId = R.string.index_name_south_america; + order = 45; + } else if (lc.startsWith("france_")) { + nameId = R.string.index_name_france; + order = 17; + } else if ( lc.contains("germany")) { + nameId = R.string.index_name_germany; + order = 16; + } else if (lc.contains("europe")) { + nameId = R.string.index_name_europe; + order = 15; + } else if (lc.contains("russia")) { + nameId = R.string.index_name_russia; + order = 18; + } else if (lc.contains("africa")) { + nameId = R.string.index_name_africa; + order = 80; + } else if (lc.contains("_asia")|| lc.startsWith("asia")) { + nameId = R.string.index_name_asia; + order = 50; + } else if (lc.contains("oceania") || lc.contains("australia")) { + nameId = R.string.index_name_oceania; + order = 70; + } else if (lc.contains("_wiki_")) { + nameId = R.string.index_name_wiki; + order = 10; + } + + String name = ctx.getString(nameId); + if (!cats.containsKey(name)) { + cats.put(name, new IndexItemCategory(name, order)); + } + cats.get(name).items.add(i); + } + ArrayList r = new ArrayList(cats.values()); + Collections.sort(r); + return r; + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/download/SrtmIndexItem.java b/OsmAnd-java/src/net/osmand/plus/download/SrtmIndexItem.java new file mode 100644 index 0000000000..c37272e697 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/download/SrtmIndexItem.java @@ -0,0 +1,140 @@ +package net.osmand.plus.download; + + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import net.osmand.IndexConstants; +import net.osmand.map.RegionCountry; +import net.osmand.plus.ClientContext; +import net.osmand.plus.R; +import net.osmand.plus.Version; + +public class SrtmIndexItem extends IndexItem { + + private RegionCountry item; + private List tilesToDownload = new ArrayList(); + public SrtmIndexItem(RegionCountry item, Map existingFileNames) { + super(fileName(item), "Elevation lines", "", item.getTileSize()+"", null); + this.item = item; + type = DownloadActivityType.SRTM_FILE; + updateExistingTiles(existingFileNames); + } + + public void updateExistingTiles(Map existingFileNames) { + tilesToDownload.clear(); + for (int i = 0; i < item.getTileSize(); i++) { + int lat = item.getLat(i); + int lon = item.getLon(i); + String fname = getFileName(lat, lon); + if (!existingFileNames.containsKey(fname + IndexConstants.BINARY_MAP_INDEX_EXT)) { + tilesToDownload.add(fname); + } + } + } + + private String getFileName(int lat, int lon) { + String fn = lat >= 0 ? "N" : "S"; + if(Math.abs(lat) < 10) { + fn += "0"; + } + fn += Math.abs(lat); + fn += lon >= 0 ? "e" : "w"; + if(Math.abs(lon) < 10) { + fn += "00"; + } else if(Math.abs(lon) < 100) { + fn += "0"; + } + fn += Math.abs(lon); + return fn; + } + + private static String fileName(RegionCountry r) { + if(r.parent == null) { + return (r.continentName + " " + r.name).trim(); + } else { + return (r.parent.continentName + " " + r.parent.name + " " + r.name).trim(); + } + } + + @Override + public boolean isAccepted() { + return true; + } + + @Override + public List createDownloadEntry(ClientContext ctx, DownloadActivityType type, + List downloadEntries) { + File parent = ctx.getAppPath(IndexConstants.SRTM_INDEX_DIR); + parent.mkdirs(); + List toDownload = new ArrayList(); + if (parent == null || !parent.exists()) { + ctx.showToastMessage(R.string.sd_dir_not_accessible); + } else { + for (String fileToDownload : tilesToDownload) { + DownloadEntry entry = new DownloadEntry(); + entry.type = type; + entry.baseName = fileToDownload; + String url = "http://" + IndexConstants.INDEX_DOWNLOAD_DOMAIN; + url += "/download?event=2&srtm=yes&"; + url += Version.getVersionAsURLParam(ctx) + "&"; + String fullName = fileToDownload + "_" + IndexConstants.BINARY_MAP_VERSION + IndexConstants.BINARY_MAP_INDEX_EXT_ZIP; + entry.urlToDownload = url +"file=" + fullName; + // url + "file=" + fileName; + entry.fileToSave = new File(parent, fullName); + entry.unzip = false; + entry.dateModified = System.currentTimeMillis(); + entry.sizeMB = 10; + entry.parts = 1; + entry.fileToUnzip = new File(parent, entry.baseName + IndexConstants.BINARY_MAP_INDEX_EXT); + downloadEntries.add(entry); + toDownload.size(); + } + } + return downloadEntries; + } + + @Override + public String getTargetFileName() { + return fileName+".nonexistent"; + } + + @Override + public String getBasename() { + return fileName; + } + + @Override + public String getSizeDescription(ClientContext ctx) { + return (item.getTileSize() - tilesToDownload.size()) + "/" + item.getTileSize() + " " + ctx.getString(R.string.index_srtm_parts); + } + + @Override + public String getVisibleDescription(ClientContext ctx) { + return ctx.getString(R.string.index_srtm_ele); + } + + @Override + public boolean isAlreadyDownloaded(Map listAlreadyDownloaded) { + for (int i = 0; i < item.getTileSize(); i++) { + int lat = item.getLat(i); + int lon = item.getLon(i); + String fname = getFileName(lat, lon); + if (listAlreadyDownloaded.containsKey(fname + IndexConstants.BINARY_MAP_INDEX_EXT)) { + return true; + } + } + return false; + } + + @Override + public String getVisibleName(ClientContext ctx) { + if(item.parent == null) { + return item.name; + } else { + return item.parent.name +" "+item.name; + } + } +} diff --git a/OsmAnd-java/src/net/osmand/plus/render/RendererRegistry.java b/OsmAnd-java/src/net/osmand/plus/render/RendererRegistry.java new file mode 100644 index 0000000000..2d2660554a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/render/RendererRegistry.java @@ -0,0 +1,165 @@ +package net.osmand.plus.render; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import net.osmand.PlatformUtil; +import net.osmand.render.RenderingRulesStorage; +import net.osmand.render.RenderingRulesStorage.RenderingRulesStorageResolver; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + + +public class RendererRegistry { + + private final static Log log = PlatformUtil.getLog(RendererRegistry.class); + + public final static String DEFAULT_RENDER = "default"; //$NON-NLS-1$ + + private RenderingRulesStorage defaultRender = null; + private RenderingRulesStorage currentSelectedRender = null; + + private Map externalRenderers = new LinkedHashMap(); + private Map internalRenderers = new LinkedHashMap(); + + private Map renderers = new LinkedHashMap(); + + public RendererRegistry(){ + internalRenderers.put(DEFAULT_RENDER, "default.render.xml"); + internalRenderers.put("Touring-view_(more-contrast-and-details)", "Touring-view_(more-contrast-and-details)" +".render.xml"); + internalRenderers.put("High-contrast-roads", "High-contrast-roads" + ".render.xml"); + internalRenderers.put("Winter-and-ski", "Winter-and-ski" + ".render.xml"); + } + + public RenderingRulesStorage defaultRender() { + if(defaultRender == null){ + defaultRender = getRenderer(DEFAULT_RENDER); + } + return defaultRender; + } + + public RenderingRulesStorage getRenderer(String name) { + if(renderers.containsKey(name)){ + return renderers.get(name); + } + if(!hasRender(name)){ + return null; + } + try { + RenderingRulesStorage r = loadRenderer(name, new LinkedHashMap(), new LinkedHashMap()); + renderers.put(name, r); + return r; + } catch (IOException e) { + log.error("Error loading renderer", e); //$NON-NLS-1$ + } catch (XmlPullParserException e) { + log.error("Error loading renderer", e); //$NON-NLS-1$ + } + return null; + } + + private boolean hasRender(String name) { + return externalRenderers.containsKey(name) || internalRenderers.containsKey(name); + } + + private RenderingRulesStorage loadRenderer(String name, final Map loadedRenderers, + final Map renderingConstants) throws IOException, XmlPullParserException { + InputStream is = getInputStream(name); + try { + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + parser.setInput(is, "UTF-8"); + int tok; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + String tagName = parser.getName(); + if (tagName.equals("renderingConstant")) { + if (!renderingConstants.containsKey(parser.getAttributeValue("", "name"))) { + renderingConstants.put(parser.getAttributeValue("", "name"), + parser.getAttributeValue("", "value")); + } + } + } + } + } finally { + is.close(); + } + + // parse content + is = getInputStream(name); + final RenderingRulesStorage main = new RenderingRulesStorage(name, renderingConstants); + + loadedRenderers.put(name, main); + try { + main.parseRulesFromXmlInputStream(is, new RenderingRulesStorageResolver() { + + @Override + public RenderingRulesStorage resolve(String name, RenderingRulesStorageResolver ref) throws XmlPullParserException { + // reload every time to propogate rendering constants + if (loadedRenderers.containsKey(name)) { + log.warn("Circular dependencies found " + name); //$NON-NLS-1$ + } + RenderingRulesStorage dep = null; + try { + dep = loadRenderer(name, loadedRenderers, renderingConstants); + } catch (IOException e) { + log.warn("Dependent renderer not found : " + e.getMessage(), e); //$NON-NLS-1$ + } + if (dep == null) { + log.warn("Dependent renderer not found : " + name); //$NON-NLS-1$ + } + return dep; + } + }); + } finally { + is.close(); + } + return main; + } + + @SuppressWarnings("resource") + private InputStream getInputStream(String name) throws FileNotFoundException { + InputStream is = null; + if(externalRenderers.containsKey(name)){ + is = new FileInputStream(externalRenderers.get(name)); + } else if(internalRenderers.containsKey(name)){ + is = RenderingRulesStorage.class.getResourceAsStream(internalRenderers.get(name)); + } else { + throw new IllegalArgumentException("Not found " + name); //$NON-NLS-1$ + } + return is; + } + + + public void setExternalRenderers(Map externalRenderers) { + this.externalRenderers = externalRenderers; + } + + public Collection getRendererNames(){ + LinkedHashSet names = new LinkedHashSet(); + names.add(DEFAULT_RENDER); + names.addAll(internalRenderers.keySet()); + names.addAll(externalRenderers.keySet()); + return names; + } + + public RenderingRulesStorage getCurrentSelectedRenderer() { + if(currentSelectedRender == null){ + return defaultRender(); + } + return currentSelectedRender; + } + + public void setCurrentSelectedRender(RenderingRulesStorage currentSelectedRender) { + this.currentSelectedRender = currentSelectedRender; + } + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/render/TextRenderer.java.bak b/OsmAnd-java/src/net/osmand/plus/render/TextRenderer.java.bak new file mode 100644 index 0000000000..6935dd9173 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/render/TextRenderer.java.bak @@ -0,0 +1,494 @@ +package net.osmand.plus.render; + + +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.procedure.TIntObjectProcedure; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.osmand.FloatMath; +import net.osmand.QuadRect; +import net.osmand.RenderingContext; +import net.osmand.binary.BinaryMapDataObject; +import net.osmand.binary.BinaryMapIndexReader.TagValuePair; +import net.osmand.data.QuadTree; +import net.osmand.plus.ClientContext; +import net.osmand.plus.api.render.Canvas; +import net.osmand.plus.api.render.Color; +import net.osmand.plus.api.render.Paint; +import net.osmand.plus.api.render.Paint.Align; +import net.osmand.plus.api.render.Paint.Style; +import net.osmand.plus.api.render.Path; +import net.osmand.plus.api.render.Typeface; +import net.osmand.render.RenderingRuleSearchRequest; +import net.osmand.render.RenderingRulesStorage; +import net.sf.junidecode.Junidecode; + +import org.w3c.dom.css.Rect; + + +public class TextRenderer { + + private Paint paintText; + private final ClientContext context; + private Paint paintIcon; + + static class TextDrawInfo { + + public TextDrawInfo(String text) { + this.text = text; + } + + String text = null; + Path drawOnPath = null; + QuadRect bounds = null; + float vOffset = 0; + float centerX = 0; + float pathRotate = 0; + float centerY = 0; + float textSize = 0; + float minDistance = 0; + int textColor = Color.BLACK; + int textShadow = 0; + int textWrap = 0; + boolean bold = false; + String shieldRes = null; + int textOrder = 100; + + public void fillProperties(RenderingRuleSearchRequest render, float centerX, float centerY) { + this.centerX = centerX; + this.centerY = centerY + render.getIntPropertyValue(render.ALL.R_TEXT_DY, 0); + // used only for draw on path where centerY doesn't play role + this.vOffset = render.getIntPropertyValue(render.ALL.R_TEXT_DY, 0); + textColor = render.getIntPropertyValue(render.ALL.R_TEXT_COLOR); + if (textColor == 0) { + textColor = Color.BLACK; + } + textSize = render.getIntPropertyValue(render.ALL.R_TEXT_SIZE); + textShadow = render.getIntPropertyValue(render.ALL.R_TEXT_HALO_RADIUS, 0); + textWrap = render.getIntPropertyValue(render.ALL.R_TEXT_WRAP_WIDTH, 0); + bold = render.getIntPropertyValue(render.ALL.R_TEXT_BOLD, 0) > 0; + minDistance = render.getIntPropertyValue(render.ALL.R_TEXT_MIN_DISTANCE, 0); + if (render.isSpecified(render.ALL.R_TEXT_SHIELD)) { + shieldRes = render.getStringPropertyValue(render.ALL.R_TEXT_SHIELD); + } + textOrder = render.getIntPropertyValue(render.ALL.R_TEXT_ORDER, 100); + } + } + + public TextRenderer(ClientContext context) { + this.context = context; + paintText = context.getRendererAPI().newPaint(); + paintText.setStyle(Style.FILL); + paintText.setStrokeWidth(1); + paintText.setColor(Color.BLACK); + paintText.setTextAlign(Align.CENTER); + paintText.setTypeface(Typeface.create("Droid Serif", Typeface.NORMAL)); //$NON-NLS-1$ + paintText.setAntiAlias(true); + + paintIcon = context.getRendererAPI().newPaint(); + paintIcon.setStyle(Style.STROKE); + } + + public Paint getPaintText() { + return paintText; + } + + private float sqr(float a) { + return a * a; + } + + boolean intersects(QuadRect tRect, float tRot, QuadRect sRect, float sRot) { + if (FloatMath.abs(tRot) < FloatMath.PI / 15 && FloatMath.abs(sRot) < FloatMath.PI / 15) { + return QuadRect.intersects(tRect, sRect); + } + double dist = FloatMath.sqrt(sqr(tRect.centerX() - sRect.centerX()) + sqr(tRect.centerY() - sRect.centerY())); + if (dist < 3) { + return true; + } + + // difference close to 90/270 degrees + if (FloatMath.abs(FloatMath.cos(tRot - sRot)) < 0.3) { + // rotate one rectangle to 90 degrees + tRot += FloatMath.PI / 2; + float l = tRect.centerX() - tRect.height() / 2; + float t = tRect.centerY() - tRect.width() / 2; + tRect = new QuadRect(l, t, l + tRect.height(), t + tRect.width()); + } + + // determine difference close to 180/0 degrees + if (FloatMath.abs(FloatMath.sin(tRot - sRot)) < 0.3) { + // rotate t box + // (calculate offset for t center suppose we rotate around s center) + float diff = (float) (-FloatMath.atan2(tRect.centerX() - sRect.centerX(), tRect.centerY() - sRect.centerY()) + Math.PI / 2); + diff -= sRot; + float left = sRect.centerX() + dist * FloatMath.cos(diff) - tRect.width() / 2f; + float top = sRect.centerY() - dist * FloatMath.sin(diff) - tRect.height() / 2f; + QuadRect nRect = new QuadRect(left, top, left + tRect.width(), top + tRect.height()); + return QuadRect.intersects(nRect, sRect); + } + + // TODO other cases not covered + return QuadRect.intersects(tRect, sRect); + } + + void drawTestBox(Canvas cv, RectF r, float rot, String text) { + cv.save(); + cv.translate(r.centerX(), r.centerY()); + cv.rotate((float) (rot * 180 / Math.PI)); + RectF rs = new RectF(-r.width() / 2, -r.height() / 2, r.width() / 2, r.height() / 2); + cv.drawRect(rs, paintIcon); + if (text != null) { + paintText.setTextSize(paintText.getTextSize() - 4); + cv.drawText(text, rs.centerX(), rs.centerY(), paintText); + paintText.setTextSize(paintText.getTextSize() + 4); + } + cv.restore(); + } + + List tempSearch = new ArrayList(); + + private boolean findTextIntersection(Canvas cv, RenderingContext rc, QuadTree boundIntersections, TextDrawInfo text) { + // for test purposes +// drawTestBox(cv, text.bounds, text.pathRotate, text.text); + boundIntersections.queryInBox(text.bounds, tempSearch); + for (int i = 0; i < tempSearch.size(); i++) { + TextDrawInfo t = tempSearch.get(i); + if (intersects(text.bounds, text.pathRotate, t.bounds, t.pathRotate)) { + return true; + } + } + if (text.minDistance > 0) { + QuadRect boundsSearch = new QuadRect(text.bounds); + boundsSearch.inset(-rc.getDensityValue(FloatMath.max(5.0f, text.minDistance)), -rc.getDensityValue(15)); + boundIntersections.queryInBox(boundsSearch, tempSearch); + // drawTestBox(cv, &boundsSearch, text.pathRotate, paintIcon, text.text, NULL/*paintText*/); + for (int i = 0; i < tempSearch.size(); i++) { + TextDrawInfo t = tempSearch.get(i); + if (t.minDistance > 0 && t.text.equals(text.text) && + intersects(boundsSearch, text.pathRotate, t.bounds, t.pathRotate)) { + return true; + } + } + } + boundIntersections.insert(text, text.bounds); + return false; + } + + private void drawTextOnCanvas(Canvas cv, String text, float centerX, float centerY, Paint paint, float textShadow) { + if (textShadow > 0) { + int c = paintText.getColor(); + paintText.setStyle(Style.STROKE); + paintText.setColor(Color.WHITE); + paintText.setStrokeWidth(2 + textShadow); + cv.drawText(text, centerX, centerY, paint); + // reset + paintText.setStrokeWidth(2); + paintText.setStyle(Style.FILL); + paintText.setColor(c); + } + cv.drawText(text, centerX, centerY, paint); + } + + public void drawTextOverCanvas(RenderingContext rc, Canvas cv, boolean useEnglishNames) { + int size = rc.textToDraw.size(); + + // 1. Sort text using text order + Collections.sort(rc.textToDraw, new Comparator() { + @Override + public int compare(TextDrawInfo object1, TextDrawInfo object2) { + return object1.textOrder - object2.textOrder; + } + }); + QuadRect r = new QuadRect(0, 0, rc.width, rc.height); + r.inset(-100, -100); + QuadTree nonIntersectedBounds = new QuadTree(r, 4, 0.6f); + + for (int i = 0; i < size; i++) { + TextDrawInfo text = rc.textToDraw.get(i); + if (text.text != null && text.text.length() > 0) { + if (useEnglishNames) { + text.text = Junidecode.unidecode(text.text); + } + + // sest text size before finding intersection (it is used there) + float textSize = rc.getDensityValue(text.textSize); + paintText.setTextSize(textSize); + paintText.setFakeBoldText(text.bold); + paintText.setColor(text.textColor); + // align center y + text.centerY += (-paintText.ascent()); + + // calculate if there is intersection + boolean intersects = findTextIntersection(cv, rc, nonIntersectedBounds, text); + if (!intersects) { + if (text.drawOnPath != null) { + if (text.textShadow > 0) { + paintText.setColor(Color.WHITE); + paintText.setStyle(Style.STROKE); + paintText.setStrokeWidth(2 + text.textShadow); + cv.drawTextOnPath(text.text, text.drawOnPath, 0, text.vOffset, paintText); + // reset + paintText.setStyle(Style.FILL); + paintText.setStrokeWidth(2); + paintText.setColor(text.textColor); + } + cv.drawTextOnPath(text.text, text.drawOnPath, 0, text.vOffset, paintText); + } else { + if (text.shieldRes != null) { + Bitmap ico = RenderingIcons.getIcon(context, text.shieldRes); + if (ico != null) { + if (rc.getDensityValue(1) != 1) { + float left = text.centerX - rc.getDensityValue(ico.getWidth() / 2) - 0.5f; + float top = text.centerY - rc.getDensityValue(ico.getHeight() / 2) - rc.getDensityValue(4.5f); + Rect rec = new Rect(0, 0, ico.getWidth(), ico.getHeight()); + cv.drawBitmap(ico, rec, + new RectF(left, top, left + rc.getDensityValue(ico.getWidth()), top + + rc.getDensityValue(ico.getHeight())), paintIcon); + } else { + float left = text.centerX - ico.getWidth() / 2 - 0.5f; + float top = text.centerY - ico.getHeight() / 2 - rc.getDensityValue(4.5f); + cv.drawBitmap(ico, left, top, paintIcon); + } + } + } + + drawWrappedText(cv, text, textSize); + } + } + } + } + } + + private void drawWrappedText(Canvas cv, TextDrawInfo text, float textSize) { + if (text.textWrap == 0) { + // set maximum for all text + text.textWrap = 40; + } + + if (text.text.length() > text.textWrap) { + int start = 0; + int end = text.text.length(); + int lastSpace = -1; + int line = 0; + int pos = 0; + int limit = 0; + while (pos < end) { + lastSpace = -1; + limit += text.textWrap; + while (pos < limit && pos < end) { + if (!Character.isLetterOrDigit(text.text.charAt(pos))) { + lastSpace = pos; + } + pos++; + } + if (lastSpace == -1 || pos == end) { + drawTextOnCanvas(cv, text.text.substring(start, pos), text.centerX, text.centerY + line * (textSize + 2), paintText, + text.textShadow); + start = pos; + } else { + drawTextOnCanvas(cv, text.text.substring(start, lastSpace), text.centerX, text.centerY + line * (textSize + 2), + paintText, text.textShadow); + start = lastSpace + 1; + limit += (start - pos) - 1; + } + line++; + + } + } else { + drawTextOnCanvas(cv, text.text, text.centerX, text.centerY, paintText, text.textShadow); + } + } + + private void createTextDrawInfo(BinaryMapDataObject o, RenderingRuleSearchRequest render, RenderingContext rc, TagValuePair pair, float xMid, float yMid, + Path path, PointF[] points, String name, String tagName) { + render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom, o); + render.setIntFilter(render.ALL.R_TEXT_LENGTH, name.length()); + render.setStringFilter(render.ALL.R_NAME_TAG, tagName); + if(render.search(RenderingRulesStorage.TEXT_RULES)){ + if(render.getIntPropertyValue(render.ALL.R_TEXT_SIZE) > 0){ + TextDrawInfo text = new TextDrawInfo(name); + text.fillProperties(render, xMid, yMid); + paintText.setTextSize(rc.getDensityValue(text.textSize)); + Rect bs = new Rect(); + paintText.getTextBounds(name, 0, name.length(), bs); + text.bounds = new QuadRect(bs.left, bs.top, bs.right, bs.bottom); + text.bounds.inset(-rc.getDensityValue(3), -rc.getDensityValue(10)); + boolean display = true; + if(path != null) { + text.drawOnPath = path; + display = calculatePathToRotate(rc, text, points, + render.getIntPropertyValue(render.ALL.R_TEXT_ON_PATH, 0) != 0); + } + if(text.drawOnPath == null) { + text.bounds.offset(text.centerX, text.centerY); + // shift to match alignment + text.bounds.offset(-text.bounds.width()/2, 0); + } else { + text.bounds.offset(text.centerX - text.bounds.width()/2, text.centerY - text.bounds.height()/2); + } + if(display) { + rc.textToDraw.add(text); + } + } + } + } + + public void renderText(final BinaryMapDataObject obj, final RenderingRuleSearchRequest render, final RenderingContext rc, + final TagValuePair pair, final float xMid, final float yMid, final Path path, final PointF[] points) { + TIntObjectHashMap map = obj.getObjectNames(); + if (map != null) { + map.forEachEntry(new TIntObjectProcedure() { + @Override + public boolean execute(int tag, String name) { + if (name != null && name.trim().length() > 0) { + createTextDrawInfo(obj, render, rc, pair, xMid, yMid, path, points, name, tag == obj.getMapIndex().nameEncodingType ? "" + : obj.getMapIndex().decodeType(tag).tag); + } + return true; + } + }); + } + } + + + boolean calculatePathToRotate(RenderingContext rc, TextDrawInfo p, PointF[] points, boolean drawOnPath) { + int len = points.length; + if (!drawOnPath) { + p.drawOnPath = null; + // simply calculate rotation of path used for shields + float px = 0; + float py = 0; + for (int i = 1; i < len; i++) { + px += points[i].x - points[i - 1].x; + py += points[i].y - points[i - 1].y; + } + if (px != 0 || py != 0) { + p.pathRotate = (float) (-FloatMath.atan2(px, py) + FloatMath.PI / 2); + } + return true; + } + + boolean inverse = false; + float roadLength = 0; + boolean prevInside = false; + float visibleRoadLength = 0; + float textw = p.bounds.width(); + int last = 0; + int startVisible = 0; + float[] distances = new float[points.length - 1]; + + float normalTextLen = 1.5f * textw; + for (int i = 0; i < len; i++, last++) { + boolean inside = points[i].x >= 0 && points[i].x <= rc.width && + points[i].x >= 0 && points[i].y <= rc.height; + if (i > 0) { + float d = FloatMath.sqrt(sqr(points[i].x - points[i - 1].x) + + sqr(points[i].y - points[i - 1].y)); + distances[i-1]= d; + roadLength += d; + if(inside) { + visibleRoadLength += d; + if(!prevInside) { + startVisible = i - 1; + } + } else if(prevInside) { + if(visibleRoadLength >= normalTextLen) { + break; + } + visibleRoadLength = 0; + } + + } + prevInside = inside; + } + if (textw >= roadLength) { + return false; + } + int startInd = 0; + int endInd = len; + + if(textw < visibleRoadLength && last - startVisible > 1) { + startInd = startVisible; + endInd = last; + // display long road name in center + if (visibleRoadLength > 3 * textw) { + boolean ch ; + do { + ch = false; + if(endInd - startInd > 2 && visibleRoadLength - distances[startInd] > normalTextLen){ + visibleRoadLength -= distances[startInd]; + startInd++; + ch = true; + } + if(endInd - startInd > 2 && visibleRoadLength - distances[endInd - 2] > normalTextLen){ + visibleRoadLength -= distances[endInd - 2]; + endInd--; + ch = true; + } + } while(ch); + } + } + // shrink path to display more text + if (startInd > 0 || endInd < len) { + // find subpath + Path path = new Path(); + for (int i = startInd; i < endInd; i++) { + if (i == startInd) { + path.moveTo(points[i].x, points[i].y); + } else { + path.lineTo(points[i].x, points[i].y); + } + } + p.drawOnPath = path; + } + // calculate vector of the road (px, py) to proper rotate it + float px = 0; + float py = 0; + for (int i = startInd + 1; i < endInd; i++) { + px += points[i].x - points[i - 1].x; + py += points[i].y - points[i - 1].y; + } + float scale = 0.5f; + float plen = (float) FloatMath.sqrt(px * px + py * py); + // vector ox,oy orthogonal to px,py to measure height + float ox = -py; + float oy = px; + if(plen > 0) { + float rot = (float) (-FloatMath.atan2(px, py) + FloatMath.PI / 2); + if (rot < 0) rot += FloatMath.PI * 2; + if (rot > FloatMath.PI / 2f && rot < 3 * FloatMath.PI / 2f) { + rot += FloatMath.PI; + inverse = true; + ox = -ox; + oy = -oy; + } + p.pathRotate = rot; + ox *= (p.bounds.height() / plen) / 2; + oy *= (p.bounds.height() / plen) / 2; + } + + p.centerX = points[startInd].x + scale * px + ox; + p.centerY = points[startInd].y + scale * py + oy; + p.vOffset += p.textSize / 2 - 1; +// p.hOffset = 0; + + if (inverse) { + Path path = new Path(); + for (int i = endInd - 1; i >= startInd; i--) { + if (i == endInd - 1) { + path.moveTo(points[i].x, points[i].y); + } else { + path.lineTo(points[i].x, points[i].y); + } + } + p.drawOnPath = path; + } + return true; + } + + +} diff --git a/OsmAnd-java/src/net/osmand/plus/routing/AlarmInfo.java b/OsmAnd-java/src/net/osmand/plus/routing/AlarmInfo.java new file mode 100644 index 0000000000..99418ffba8 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/AlarmInfo.java @@ -0,0 +1,101 @@ +package net.osmand.plus.routing; + +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; + +public class AlarmInfo { + public static int SPEED_CAMERA = 1; + public static int SPEED_LIMIT = SPEED_CAMERA + 1; + public static int BORDER_CONTROL = SPEED_LIMIT + 1; + public static int TRAFFIC_CALMING = BORDER_CONTROL + 1; + public static int TOLL_BOOTH = TRAFFIC_CALMING + 1; + public static int STOP = TOLL_BOOTH + 1; + public static int MAXIMUM = STOP + 1; + + private int type; + private float distance; + private float time; + protected final int locationIndex; + private int intValue; + + public AlarmInfo(int type, int locationIndex){ + this.type = type; + this.locationIndex = locationIndex; + } + + public float getDistance() { + return distance; + } + + public float getTime() { + return time; + } + + + public void setTime(float time) { + this.time = time; + } + + public void setDistance(float distance) { + this.distance = distance; + } + + public int getType() { + return type; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + + + public static AlarmInfo createSpeedLimit(int speed){ + AlarmInfo info = new AlarmInfo(SPEED_LIMIT, 0); + info.setIntValue(speed); + return info; + } + + public static AlarmInfo createAlarmInfo(RouteTypeRule ruleType, int locInd) { + if("highway".equals(ruleType.getTag())) { + if("speed_camera".equals(ruleType.getValue())) { + return new AlarmInfo(SPEED_CAMERA, locInd); + } else if("stop".equals(ruleType.getValue())) { + return new AlarmInfo(STOP, locInd); + } + } else if("barrier".equals(ruleType.getTag())) { + if("toll_booth".equals(ruleType.getValue())) { + return new AlarmInfo(TOLL_BOOTH, locInd); + } else if("border_control".equals(ruleType.getValue())) { + return new AlarmInfo(BORDER_CONTROL, locInd); + } + } else if("traffic_calming".equals(ruleType.getTag())) { + return new AlarmInfo(TRAFFIC_CALMING, locInd); + } + return null; + } + + public int updateDistanceAndGetPriority(float time, float distance) { + this.distance = distance; + this.time = time; + if (distance > 1500) { + return 0; + } + // 1 level of priorities + if (time < 8 || distance < 100 || type == SPEED_LIMIT) { + return type; + } + if (type == SPEED_CAMERA && (time < 15 || distance < 150)) { + return type; + } + // 2nd level + if (time < 10 || distance < 150) { + return type + MAXIMUM; + } + return 0; + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/routing/RouteCalculationParams.java b/OsmAnd-java/src/net/osmand/plus/routing/RouteCalculationParams.java new file mode 100644 index 0000000000..9cf6a51088 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/RouteCalculationParams.java @@ -0,0 +1,29 @@ +package net.osmand.plus.routing; + +import java.util.List; + +import net.osmand.Location; +import net.osmand.data.LatLon; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.ClientContext; +import net.osmand.plus.routing.RouteProvider.GPXRouteParams; +import net.osmand.plus.routing.RouteProvider.RouteService; +import net.osmand.router.RouteCalculationProgress; + +public class RouteCalculationParams { + + public Location start; + public LatLon end; + public List intermediates; + + public ClientContext ctx; + public ApplicationMode mode; + public RouteService type; + public GPXRouteParams gpxRoute; + public RouteCalculationResult previousToRecalculate; + public boolean fast; + public boolean optimal; + public boolean leftSide; + public RouteCalculationProgress calculationProgress; + public boolean preciseRouting; +} diff --git a/OsmAnd-java/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd-java/src/net/osmand/plus/routing/RouteCalculationResult.java new file mode 100644 index 0000000000..10052a4cdc --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/RouteCalculationResult.java @@ -0,0 +1,848 @@ +package net.osmand.plus.routing; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.osmand.Location; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; +import net.osmand.data.LatLon; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.ClientContext; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.router.RouteSegmentResult; +import net.osmand.router.TurnType; +import net.osmand.util.MapUtils; + +public class RouteCalculationResult { + // could not be null and immodifiable! + private final List locations; + private final List directions; + private final List segments; + private final List alarmInfo; + private final String errorMessage; + private final int[] listDistance; + private final int[] intermediatePoints; + private final float routingTime; + + + // Note always currentRoute > get(currentDirectionInfo).routeOffset, + // but currentRoute <= get(currentDirectionInfo+1).routeOffset + protected int currentDirectionInfo = 0; + protected int currentRoute = 0; + protected int nextIntermediate = 0; + protected int nextAlarmInfo = 0; + + public RouteCalculationResult(String errorMessage) { + this(null, null, null, null, null, errorMessage, null, false, false); + } + + public RouteCalculationResult(List list, List directions, Location start, LatLon end, + List intermediates, String errorMessage, ClientContext ctx, boolean leftSide, boolean addMissingTurns) { + this.routingTime = 0; + this.errorMessage = errorMessage; + this.intermediatePoints = new int[intermediates == null ? 0 : intermediates.size()]; + List locations = list == null ? new ArrayList() : new ArrayList(list); + List localDirections = directions == null? new ArrayList() : new ArrayList(directions); + if (!locations.isEmpty()) { + checkForDuplicatePoints(locations, localDirections); + } + if(addMissingTurns) { + removeUnnecessaryGoAhead(localDirections); + OsmandSettings settings = ctx.getSettings(); + addMissingTurnsToRoute(locations, localDirections, start, end, settings.getApplicationMode(), ctx, leftSide); + // if there is no closest points to start - add it + introduceFirstPointAndLastPoint(locations, localDirections, null, start, end); + } + + this.locations = Collections.unmodifiableList(locations); + this.segments = new ArrayList(); + this.listDistance = new int[locations.size()]; + updateListDistanceTime(); + this.alarmInfo = new ArrayList(); + calculateIntermediateIndexes(ctx, intermediates, localDirections); + this.directions = Collections.unmodifiableList(localDirections); + updateDirectionsTime(); + } + + public RouteCalculationResult(List list, Location start, LatLon end, List intermediates, + ClientContext ctx, boolean leftSide, float routingTime) { + this.routingTime = routingTime; + List computeDirections = new ArrayList(); + this.errorMessage = null; + this.intermediatePoints = new int[intermediates == null ? 0 : intermediates.size()]; + List locations = new ArrayList(); + ArrayList alarms = new ArrayList(); + List segments = convertVectorResult(computeDirections, locations, list, alarms, ctx); + introduceFirstPointAndLastPoint(locations, computeDirections, segments, start, end); + + this.locations = Collections.unmodifiableList(locations); + this.segments = Collections.unmodifiableList(segments); + this.listDistance = new int[locations.size()]; + calculateIntermediateIndexes(ctx, intermediates, computeDirections); + updateListDistanceTime(); + + this.directions = Collections.unmodifiableList(computeDirections); + updateDirectionsTime(); + this.alarmInfo = Collections.unmodifiableList(alarms); + + } + + private void calculateIntermediateIndexes(ClientContext ctx, List intermediates, List localDirections) { + if(intermediates != null && localDirections != null) { + int[] interLocations = new int[intermediates.size()]; + int currentIntermediate = 0; + int currentLocation = 0; + double distanceThreshold = 25; + double prevDistance = distanceThreshold * 4; + while((currentIntermediate < intermediates.size() || prevDistance > distanceThreshold) + && currentLocation < this.locations.size()){ + if(currentIntermediate < intermediates.size() && + getDistanceToLocation(intermediates.get(currentIntermediate), currentLocation) < 50) { + prevDistance = getDistanceToLocation(intermediates.get(currentIntermediate), currentLocation); + interLocations[currentIntermediate] = currentLocation; + currentIntermediate++; + } else if(currentIntermediate > 0 && prevDistance > distanceThreshold && + getDistanceToLocation(intermediates.get(currentIntermediate - 1), + currentLocation) < prevDistance) { + prevDistance = getDistanceToLocation(intermediates.get(currentIntermediate - 1), currentLocation); + interLocations[currentIntermediate - 1] = currentLocation; + } + currentLocation ++; + } + int currentDirection = 0; + currentIntermediate = 0; + while(currentIntermediate < intermediates.size() && currentDirection < localDirections.size()){ + int locationIndex = localDirections.get(currentDirection).routePointOffset ; + if (locationIndex >= interLocations[currentIntermediate]) { + // split directions + if (locationIndex > interLocations[currentIntermediate] + && getDistanceToLocation(intermediates.get(currentIntermediate), locationIndex) > 50) { + RouteDirectionInfo toSplit = localDirections.get(currentDirection); + RouteDirectionInfo info = new RouteDirectionInfo(localDirections.get(currentDirection).getAverageSpeed(), TurnType.valueOf(TurnType.C, + false)); + info.setRef(toSplit.getRef()); + info.setStreetName(toSplit.getStreetName()); + info.setDestinationName(toSplit.getDestinationName()); + info.routePointOffset = interLocations[currentIntermediate]; + info.setDescriptionRoute(ctx.getString(R.string.route_head));//; //$NON-NLS-1$ + localDirections.add(currentDirection, info); + } + intermediatePoints[currentIntermediate] = currentDirection; + currentIntermediate++; + } + currentDirection ++; + } + } + } + + private double getDistanceToLocation(LatLon p, int currentLocation) { + return MapUtils.getDistance(p, + this.locations.get(currentLocation).getLatitude(), this.locations.get(currentLocation).getLongitude()); + } + + private void attachAlarmInfo(List alarms, RouteSegmentResult res, int intId, int locInd) { + int[] pointTypes = res.getObject().getPointTypes(intId); + RouteRegion reg = res.getObject().region; + if (pointTypes != null) { + for (int r = 0; r < pointTypes.length; r++) { + RouteTypeRule typeRule = reg.quickGetEncodingRule(pointTypes[r]); + AlarmInfo info = AlarmInfo.createAlarmInfo(typeRule, locInd); + if(info != null) { + alarms.add(info); + } + } + } + } + + public List getOriginalRoute() { + if (segments.size() == 0) { + return null; + } + List list = new ArrayList(); + list.add(segments.get(0)); + for (int i = 1; i < segments.size(); i++) { + if (segments.get(i - 1) != segments.get(i)) { + list.add(segments.get(i)); + } + } + return list; + } + + /** + * PREPARATION + */ + private List convertVectorResult(List directions, List locations, List list, + List alarms, ClientContext ctx) { + float prevDirectionTime = 0; + float prevDirectionDistance = 0; + List segmentsToPopulate = new ArrayList(); + for (int routeInd = 0; routeInd < list.size(); routeInd++) { + RouteSegmentResult s = list.get(routeInd); + boolean plus = s.getStartPointIndex() < s.getEndPointIndex(); + int i = s.getStartPointIndex(); + int prevLocationSize = locations.size(); + while (true) { + Location n = new Location(""); //$NON-NLS-1$ + LatLon point = s.getPoint(i); + n.setLatitude(point.getLatitude()); + n.setLongitude(point.getLongitude()); + if (i == s.getEndPointIndex() && routeInd != list.size() - 1) { + break; + } + locations.add(n); + attachAlarmInfo(alarms, s, i, locations.size()); + segmentsToPopulate.add(s); + if (i == s.getEndPointIndex() ) { + break; + } + if (plus) { + i++; + } else { + i--; + } + } + TurnType turn = s.getTurnType(); + + if(turn != null) { + RouteDirectionInfo info = new RouteDirectionInfo(s.getSegmentSpeed(), turn); + if(routeInd + 1< list.size()) { + RouteSegmentResult next = list.get(routeInd); + info.setRef(next.getObject().getRef()); + info.setStreetName(next.getObject().getName()); + info.setDestinationName(next.getObject().getDestinationName()); + } + + String description = toString(turn, ctx); + info.setDescriptionRoute(description); + info.routePointOffset = prevLocationSize; + if(directions.size() > 0 && prevDirectionTime > 0 && prevDirectionDistance > 0) { + RouteDirectionInfo prev = directions.get(directions.size() - 1); + prev.setAverageSpeed(prevDirectionDistance / prevDirectionTime); + prev.setDescriptionRoute(prev.getDescriptionRoute() + " " + OsmAndFormatter.getFormattedDistance(prevDirectionDistance, ctx)); + prevDirectionDistance = 0; + prevDirectionTime = 0; + } + directions.add(info); + } + prevDirectionDistance += s.getDistance(); + prevDirectionTime += s.getSegmentTime(); + } + if(directions.size() > 0 && prevDirectionTime > 0 && prevDirectionDistance > 0) { + RouteDirectionInfo prev = directions.get(directions.size() - 1); + prev.setAverageSpeed(prevDirectionDistance / prevDirectionTime); + prev.setDescriptionRoute(prev.getDescriptionRoute() + " " + OsmAndFormatter.getFormattedDistance(prevDirectionDistance, ctx)); + } + return segmentsToPopulate; + } + + protected void addMissingTurnsToRoute(List locations, + List originalDirections, Location start, LatLon end, ApplicationMode mode, ClientContext ctx, + boolean leftSide){ + if(locations.isEmpty()){ + return; + } + // speed m/s + float speed = 1.5f; + int minDistanceForTurn = 5; + if(mode == ApplicationMode.CAR){ + speed = 15.3f; + minDistanceForTurn = 35; + } else if(mode == ApplicationMode.BICYCLE){ + speed = 5.5f; + minDistanceForTurn = 12; + } + + List computeDirections = new ArrayList(); + + int[] listDistance = new int[locations.size()]; + listDistance[locations.size() - 1] = 0; + for (int i = locations.size() - 1; i > 0; i--) { + listDistance[i - 1] = (int) locations.get(i - 1).distanceTo(locations.get(i)); + listDistance[i - 1] += listDistance[i]; + } + + int previousLocation = 0; + int prevBearingLocation = 0; + RouteDirectionInfo previousInfo = new RouteDirectionInfo(speed, TurnType.valueOf(TurnType.C, leftSide)); + previousInfo.routePointOffset = 0; + previousInfo.setDescriptionRoute(ctx.getString( R.string.route_head)); + computeDirections.add(previousInfo); + + int distForTurn = 0; + float previousBearing = 0; + int startTurnPoint = 0; + + + for (int i = 1; i < locations.size() - 1; i++) { + + Location next = locations.get(i + 1); + Location current = locations.get(i); + float bearing = current.bearingTo(next); + // try to get close to current location if possible + while(prevBearingLocation < i - 1){ + if(locations.get(prevBearingLocation + 1).distanceTo(current) > 70){ + prevBearingLocation ++; + } else { + break; + } + } + + if(distForTurn == 0){ + // measure only after turn + previousBearing = locations.get(prevBearingLocation).bearingTo(current); + startTurnPoint = i; + } + + TurnType type = null; + String description = null; + float delta = previousBearing - bearing; + while(delta < 0){ + delta += 360; + } + while(delta > 360){ + delta -= 360; + } + + distForTurn += locations.get(i).distanceTo(locations.get(i + 1)); + if (i < locations.size() - 1 && distForTurn < minDistanceForTurn) { + // For very smooth turn we try to accumulate whole distance + // simply skip that turn needed for situation + // 1) if you are going to have U-turn - not 2 left turns + // 2) if there is a small gap between roads (turn right and after 4m next turn left) - so the direction head + continue; + } + + + if(delta > 45 && delta < 315){ + + if(delta < 60){ + type = TurnType.valueOf(TurnType.TSLL, leftSide); + description = ctx.getString( R.string.route_tsll); + } else if(delta < 120){ + type = TurnType.valueOf(TurnType.TL, leftSide); + description = ctx.getString( R.string.route_tl); + } else if(delta < 150){ + type = TurnType.valueOf(TurnType.TSHL, leftSide); + description = ctx.getString( R.string.route_tshl); + } else if(delta < 210){ + type = TurnType.valueOf(TurnType.TU, leftSide); + description = ctx.getString( R.string.route_tu); + } else if(delta < 240){ + description = ctx.getString( R.string.route_tshr); + type = TurnType.valueOf(TurnType.TSHR, leftSide); + } else if(delta < 300){ + description = ctx.getString( R.string.route_tr); + type = TurnType.valueOf(TurnType.TR, leftSide); + } else { + description = ctx.getString( R.string.route_tslr); + type = TurnType.valueOf(TurnType.TSLR, leftSide); + } + + // calculate for previousRoute + previousInfo.distance = listDistance[previousLocation]- listDistance[i]; + previousInfo.setDescriptionRoute(previousInfo.getDescriptionRoute() + + " " + OsmAndFormatter.getFormattedDistance(previousInfo.distance, ctx)); //$NON-NLS-1$ + type.setTurnAngle(360 - delta); + previousInfo = new RouteDirectionInfo(speed, type); + previousInfo.setDescriptionRoute(description); + previousInfo.routePointOffset = startTurnPoint; + computeDirections.add(previousInfo); + previousLocation = startTurnPoint; + prevBearingLocation = i; // for bearing using current location + } + // clear dist for turn + distForTurn = 0; + } + + previousInfo.distance = listDistance[previousLocation]; + previousInfo.setDescriptionRoute(previousInfo.getDescriptionRoute() + + " " + OsmAndFormatter.getFormattedDistance(previousInfo.distance, ctx)); //$NON-NLS-1$ + + if (originalDirections.isEmpty()) { + originalDirections.addAll(computeDirections); + } else { + int currentDirection = 0; + // one more + for (int i = 0; i <= originalDirections.size() && currentDirection < computeDirections.size(); i++) { + while (currentDirection < computeDirections.size()) { + int distanceAfter = 0; + if (i < originalDirections.size()) { + RouteDirectionInfo resInfo = originalDirections.get(i); + int r1 = computeDirections.get(currentDirection).routePointOffset; + int r2 = resInfo.routePointOffset; + distanceAfter = listDistance[resInfo.routePointOffset]; + float dist = locations.get(r1).distanceTo(locations.get(r2)); + // take into account that move roundabout is special turn that could be very lengthy + if (dist < 100) { + // the same turn duplicate + currentDirection++; + continue; // while cycle + } else if (computeDirections.get(currentDirection).routePointOffset > resInfo.routePointOffset) { + // check it at the next point + break; + } + } + + // add turn because it was missed + RouteDirectionInfo toAdd = computeDirections.get(currentDirection); + + if (i > 0) { + // update previous + RouteDirectionInfo previous = originalDirections.get(i - 1); + toAdd.setAverageSpeed(previous.getAverageSpeed()); + } + toAdd.distance = listDistance[toAdd.routePointOffset] - distanceAfter; + if (i < originalDirections.size()) { + originalDirections.add(i, toAdd); + } else { + originalDirections.add(toAdd); + } + i++; + currentDirection++; + } + } + + } + + int sum = 0; + for (int i = originalDirections.size() - 1; i >= 0; i--) { + originalDirections.get(i).afterLeftTime = sum; + sum += originalDirections.get(i).getExpectedTime(); + } + } + + + public String toString(TurnType type, ClientContext ctx) { + if(type.isRoundAbout()){ + return ctx.getString(R.string.route_roundabout, type.getExitOut()); + } else if(type.getValue().equals(TurnType.C)) { + return ctx.getString(R.string.route_head); + } else if(type.getValue().equals(TurnType.TSLL)) { + return ctx.getString(R.string.route_tsll); + } else if(type.getValue().equals(TurnType.TL)) { + return ctx.getString(R.string.route_tl); + } else if(type.getValue().equals(TurnType.TSHL)) { + return ctx.getString(R.string.route_tshl); + } else if(type.getValue().equals(TurnType.TSLR)) { + return ctx.getString(R.string.route_tslr); + } else if(type.getValue().equals(TurnType.TR)) { + return ctx.getString(R.string.route_tr); + } else if(type.getValue().equals(TurnType.TSHR)) { + return ctx.getString(R.string.route_tshr); + } else if(type.getValue().equals(TurnType.TU)) { + return ctx.getString(R.string.route_tu); + } else if(type.getValue().equals(TurnType.TRU)) { + return ctx.getString(R.string.route_tu); + } else if(type.getValue().equals(TurnType.KL)) { + return ctx.getString(R.string.route_kl); + } else if(type.getValue().equals(TurnType.KR)) { + return ctx.getString(R.string.route_kr); + } + return ""; + } + + public String getErrorMessage() { + return errorMessage; + } + + + /** + * PREPARATION + * Remove unnecessary go straight from CloudMade. + * Remove also last direction because it will be added after. + */ + private void removeUnnecessaryGoAhead(List directions) { + if (directions != null && directions.size() > 1) { + for (int i = 1; i < directions.size();) { + RouteDirectionInfo r = directions.get(i); + if (r.getTurnType().getValue().equals(TurnType.C)) { + RouteDirectionInfo prev = directions.get(i - 1); + prev.setAverageSpeed((prev.distance + r.distance) + / (prev.distance / prev.getAverageSpeed() + r.distance / r.getAverageSpeed())); + directions.remove(i); + } else { + i++; + } + } + } + } + + /** + * PREPARATION + * Check points for duplicates (it is very bad for routing) - cloudmade could return it + */ + private void checkForDuplicatePoints(List locations, List directions) { + // + for (int i = 0; i < locations.size() - 1;) { + if (locations.get(i).distanceTo(locations.get(i + 1)) == 0) { + locations.remove(i); + if (directions != null) { + for (RouteDirectionInfo info : directions) { + if (info.routePointOffset > i) { + info.routePointOffset--; + } + } + } + } else { + i++; + } + } + } + + /** + * PREPARATION + * If beginning is too far from start point, then introduce GO Ahead + * @param end + */ + private void introduceFirstPointAndLastPoint(List locations, List directions, List segs, Location start, + LatLon end) { + if (!locations.isEmpty() && locations.get(0).distanceTo(start) > 200) { + // add start point + locations.add(0, start); + if(segs != null) { + segs.add(0, segs.get(0)); + } + if (directions != null && !directions.isEmpty()) { + for (RouteDirectionInfo i : directions) { + i.routePointOffset++; + } + RouteDirectionInfo info = new RouteDirectionInfo(directions.get(0).getAverageSpeed(), + TurnType.valueOf(TurnType.C, false)); + info.routePointOffset = 0; + // info.setDescriptionRoute(ctx.getString( R.string.route_head));//; //$NON-NLS-1$ + directions.add(0, info); + } + } + RouteDirectionInfo lastDirInf = directions.size() > 0 ? directions.get(directions.size() - 1) : null; + if((lastDirInf == null || lastDirInf.routePointOffset < locations.size() - 1) && locations.size() - 1 > 0) { + String type = TurnType.C; + Location prevLast = locations.get(locations.size() - 2); + float lastBearing = prevLast.bearingTo(locations.get(locations.size() - 1)); + float[] compute = new float[2]; + Location.distanceBetween(prevLast.getLatitude(), prevLast.getLongitude(), + end.getLatitude(), end.getLongitude(), compute); + float bearingToEnd = compute[1]; + double diff = MapUtils.degreesDiff(lastBearing, bearingToEnd); + if(Math.abs(diff) > 10) { + type = diff > 0 ? TurnType.KL : TurnType.KR; + } + RouteDirectionInfo info = new RouteDirectionInfo(1, TurnType.valueOf(type, false)); + info.distance = 0; + info.afterLeftTime = 0; + info.routePointOffset = locations.size() - 1; + directions.add(info); + } + } + + /** + * PREPARATION + * At the end always update listDistance local vars and time + */ + private void updateListDistanceTime() { + if (listDistance.length > 0) { + listDistance[locations.size() - 1] = 0; + for (int i = locations.size() - 1; i > 0; i--) { + listDistance[i - 1] = (int) locations.get(i - 1).distanceTo(locations.get(i)); + listDistance[i - 1] += listDistance[i]; + } + } + } + + /** + * PREPARATION + * At the end always update listDistance local vars and time + */ + private void updateDirectionsTime() { + int sum = 0; + for (int i = directions.size() - 1; i >= 0; i--) { + directions.get(i).afterLeftTime = sum; + directions.get(i).distance = listDistance[directions.get(i).routePointOffset]; + if (i < directions.size() - 1) { + directions.get(i).distance -= listDistance[directions.get(i + 1).routePointOffset]; + } + sum += directions.get(i).getExpectedTime(); + } + } + + //////////////////// MUST BE ALL SYNCHRONIZED ??? ////////////////////// + + public List getImmutableLocations() { + return locations; + } + + public List getDirections() { + return directions; + } + + + public List getNextLocations() { + if(currentRoute < locations.size()) { + return locations.subList(currentRoute, locations.size()); + } + return Collections.emptyList(); + } + + public RouteSegmentResult getCurrentSegmentResult() { + int cs = currentRoute > 0 ? currentRoute - 1 : 0; + if(cs < segments.size()) { + return segments.get(cs); + } + return null; + } + + public float getCurrentMaxSpeed() { + RouteSegmentResult res = getCurrentSegmentResult(); + if(res != null) { + return res.getObject().getMaximumSpeed(); + } + return 0; + } + + public float getRoutingTime() { + return routingTime; + } + + + public int getWholeDistance() { + if(listDistance.length > 0) { + return listDistance[0]; + } + return 0; + } + + public boolean isCalculated() { + return !locations.isEmpty(); + } + + public boolean isEmpty() { + return locations.isEmpty() || currentRoute >= locations.size(); + } + + + public void updateCurrentRoute(int currentRoute) { + this.currentRoute = currentRoute; + while (currentDirectionInfo < directions.size() - 1 && directions.get(currentDirectionInfo + 1).routePointOffset < currentRoute) { + currentDirectionInfo++; + } + while (nextAlarmInfo < alarmInfo.size() && alarmInfo.get(nextAlarmInfo).locationIndex < currentRoute) { + nextAlarmInfo++; + } + while(nextIntermediate < intermediatePoints.length) { + RouteDirectionInfo dir = directions.get(intermediatePoints[nextIntermediate]); + if(dir.routePointOffset < currentRoute) { + nextIntermediate ++; + } else { + break; + } + } + } + + public void passIntermediatePoint(){ + nextIntermediate ++ ; + } + + public Location getLocationFromRouteDirection(RouteDirectionInfo i){ + if(i.routePointOffset < locations.size()){ + return locations.get(i.routePointOffset); + } + return null; + } + + + /*public */NextDirectionInfo getNextRouteDirectionInfo(NextDirectionInfo info, Location fromLoc, boolean toSpeak) { + int dirInfo = currentDirectionInfo; + if (dirInfo < directions.size()) { + int dist = listDistance[currentRoute]; + int nextInd = dirInfo + 1; + if (toSpeak) { + while (nextInd < directions.size()) { + RouteDirectionInfo i = directions.get(nextInd); + if (i.getTurnType() != null && !i.getTurnType().isSkipToSpeak()) { + break; + } + nextInd++; + } + } + if (fromLoc != null) { + dist += fromLoc.distanceTo(locations.get(currentRoute)); + } + if (nextInd < directions.size()) { + info.directionInfo = directions.get(nextInd); + dist -= listDistance[directions.get(nextInd).routePointOffset]; + } + if(intermediatePoints != null && nextIntermediate < intermediatePoints.length) { + info.intermediatePoint = intermediatePoints[nextIntermediate] == nextInd; + } + info.directionInfoInd = nextInd; + info.distanceTo = dist; + return info; + } + info.directionInfoInd = -1; + info.distanceTo = -1; + info.directionInfo = null; + return null; + } + + /*public */NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo prev, NextDirectionInfo next, boolean toSpeak) { + int dirInfo = prev.directionInfoInd; + if (dirInfo < directions.size() && prev.directionInfo != null) { + int dist = listDistance[prev.directionInfo.routePointOffset]; + int nextInd = dirInfo + 1; + if (toSpeak) { + while (nextInd < directions.size()) { + RouteDirectionInfo i = directions.get(nextInd); + if (i.getTurnType() != null && !i.getTurnType().isSkipToSpeak()) { + break; + } + nextInd++; + } + } + if (nextInd < directions.size()) { + next.directionInfo = directions.get(nextInd); + dist -= listDistance[directions.get(nextInd).routePointOffset]; + } + if(intermediatePoints != null && nextIntermediate < intermediatePoints.length) { + next.intermediatePoint = intermediatePoints[nextIntermediate] == nextInd; + } + next.distanceTo = dist; + next.directionInfoInd = nextInd; + return next; + } + next.directionInfoInd = -1; + next.distanceTo = -1; + next.directionInfo = null; + return null; + } + + public List getRouteDirections() { + if(currentDirectionInfo < directions.size()){ + if(currentDirectionInfo == 0){ + return directions; + } + if(currentDirectionInfo < directions.size() - 1){ + return directions.subList(currentDirectionInfo + 1, directions.size()); + } + } + return Collections.emptyList(); + } + + public Location getNextRouteLocation() { + if(currentRoute < locations.size()) { + return locations.get(currentRoute); + } + return null; + } + + public AlarmInfo getMostImportantAlarm(Location fromLoc, AlarmInfo speedAlarm, boolean showCameras) { + int cRoute = currentRoute; + AlarmInfo mostImportant = speedAlarm; + int value = speedAlarm != null? speedAlarm.updateDistanceAndGetPriority(0, 0) : Integer.MAX_VALUE; + int aInfo = nextAlarmInfo; + if (aInfo < alarmInfo.size()) { + int dist = 0; + float speed = 0; + if (fromLoc != null && fromLoc.hasSpeed()) { + speed = fromLoc.getSpeed(); + } + if (fromLoc != null) { + dist += fromLoc.distanceTo(locations.get(cRoute)); + } + dist += listDistance[cRoute]; + while(aInfo < alarmInfo.size()) { + AlarmInfo inf = alarmInfo.get(aInfo); + int d = dist - listDistance[inf.locationIndex]; + if(d > 700){ + break; + } + float time = speed > 0 ? d / speed : Integer.MAX_VALUE; + int vl = inf.updateDistanceAndGetPriority(time, d); + if(vl < value && (showCameras || inf.getType() != AlarmInfo.SPEED_CAMERA)){ + mostImportant = inf; + value = vl; + } + aInfo++; + } + } + return mostImportant; + } + + public Location getNextRouteLocation(int after) { + if(currentRoute + after < locations.size()) { + return locations.get(currentRoute + after); + } + return null; + } + + public boolean directionsAvailable(){ + return currentDirectionInfo < directions.size(); + } + + public int getDistanceToFinish(Location fromLoc) { + if(listDistance != null && currentRoute < listDistance.length){ + int dist = listDistance[currentRoute]; + Location l = locations.get(currentRoute); + if(fromLoc != null){ + dist += fromLoc.distanceTo(l); + } + return dist; + } + return 0; + } + + public int getDistanceToNextIntermediate(Location fromLoc) { + if(listDistance != null && currentRoute < listDistance.length){ + int dist = listDistance[currentRoute]; + Location l = locations.get(currentRoute); + if(fromLoc != null){ + dist += fromLoc.distanceTo(l); + } + if(nextIntermediate >= intermediatePoints.length ){ + return 0; + } else { + int directionInd = intermediatePoints[nextIntermediate]; + return dist - listDistance[directions.get(directionInd).routePointOffset]; + } + } + return 0; + } + + public int getIntermediatePointsToPass(){ + if(nextIntermediate >= intermediatePoints.length) { + return 0; + } + return intermediatePoints.length - nextIntermediate; + } + + public int getLeftTime(Location fromLoc){ + int time = 0; + if(currentDirectionInfo < directions.size()) { + RouteDirectionInfo current = directions.get(currentDirectionInfo); + time = current.afterLeftTime; + + int distanceToNextTurn = listDistance[currentRoute]; + if(currentDirectionInfo + 1 < directions.size()) { + distanceToNextTurn -= listDistance[directions.get(currentDirectionInfo + 1).routePointOffset]; + } + Location l = locations.get(currentRoute); + if(fromLoc != null){ + distanceToNextTurn += fromLoc.distanceTo(l); + } + time += distanceToNextTurn / current.getAverageSpeed(); + } + return time; + } + + + public static class NextDirectionInfo { + public RouteDirectionInfo directionInfo; + public int distanceTo; + public boolean intermediatePoint; + public int imminent; + private int directionInfoInd; + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/routing/RouteDirectionInfo.java b/OsmAnd-java/src/net/osmand/plus/routing/RouteDirectionInfo.java new file mode 100644 index 0000000000..3b42b7cb9d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/RouteDirectionInfo.java @@ -0,0 +1,83 @@ +package net.osmand.plus.routing; + +import net.osmand.router.TurnType; + +public class RouteDirectionInfo { + // location when you should action (turn or go ahead) + public int routePointOffset; + // Type of action to take + private TurnType turnType; + // Description of the turn and route after + private String descriptionRoute = ""; //$NON-NLS-1$ + // Speed after the action till next turn + private float averageSpeed; + + private String ref; + + private String streetName; + + private String destinationName; + + public String getDestinationName() { + return destinationName; + } + + public void setDestinationName(String destinationName) { + this.destinationName = destinationName; + } + + // Constructor to verify average speed always > 0 + public RouteDirectionInfo(float averageSpeed, TurnType turnType) { + this.averageSpeed = averageSpeed == 0 ? 1 : averageSpeed; + this.turnType = turnType; + } + + public String getDescriptionRoute() { + return descriptionRoute; + } + + public String getRef() { + return ref; + } + + public void setRef(String ref) { + this.ref = ref; + } + + public String getStreetName() { + return streetName; + } + + public void setStreetName(String streetName) { + this.streetName = streetName; + } + + public void setDescriptionRoute(String descriptionRoute) { + this.descriptionRoute = descriptionRoute; + } + + public float getAverageSpeed() { + return averageSpeed; + } + + public void setAverageSpeed(float averageSpeed) { + this.averageSpeed = averageSpeed == 0 ? 1 : averageSpeed; + } + + // expected time after route point + public int getExpectedTime() { + return (int) (distance / averageSpeed); + } + + + public TurnType getTurnType() { + return turnType; + } + + + // calculated vars + // after action (excluding expectedTime) + public int afterLeftTime; + // distance after action (for i.e. after turn to next turn) + public int distance; +} diff --git a/OsmAnd-java/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd-java/src/net/osmand/plus/routing/RouteProvider.java new file mode 100644 index 0000000000..764a2d90c6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/RouteProvider.java @@ -0,0 +1,725 @@ +package net.osmand.plus.routing; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; + +import net.osmand.IndexConstants; +import net.osmand.Location; +import net.osmand.PlatformUtil; +import net.osmand.NativeLibrary; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.data.LatLon; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.ClientContext; +import net.osmand.plus.GPXUtilities; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.GPXUtilities.GPXFile; +import net.osmand.plus.GPXUtilities.Route; +import net.osmand.plus.GPXUtilities.Track; +import net.osmand.plus.GPXUtilities.TrkSegment; +import net.osmand.plus.GPXUtilities.WptPt; +import net.osmand.router.GeneralRouter; +import net.osmand.router.GeneralRouter.GeneralRouterProfile; +import net.osmand.router.RoutePlannerFrontEnd; +import net.osmand.router.RouteSegmentResult; +import net.osmand.router.RoutingConfiguration; +import net.osmand.router.RoutingContext; +import net.osmand.router.TurnType; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xmlpull.v1.XmlPullParserException; + + +public class RouteProvider { + private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RouteProvider.class); + private static final String OSMAND_ROUTER = "OsmAndRouter"; + + public enum RouteService { + OSMAND("OsmAnd (offline)"), CLOUDMADE("CloudMade"), YOURS("YOURS"), ORS("OpenRouteService"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + private final String name; + private RouteService(String name){ + this.name = name; + } + public String getName() { + return name; + } + } + + public RouteProvider(){ + } + + public static class GPXRouteParams { + List points = new ArrayList(); + List directions; + + public GPXRouteParams(GPXFile file, boolean reverse, OsmandSettings settings){ + prepareEverything(file, reverse, settings.LEFT_SIDE_NAVIGATION.get()); + } + + public void setStartPoint(Location startPoint) { + points.add(0, startPoint); + } + + public List getPoints() { + return points; + } + + public Location getStartPointForRoute(){ + if(!points.isEmpty()){ + return points.get(0); + } + return null; + } + + public LatLon getLastPoint() { + if(!points.isEmpty()){ + Location l = points.get(points.size() - 1); + LatLon point = new LatLon(l.getLatitude(), l.getLongitude()); + return point; + } + return null; + } + + private void prepareEverything(GPXFile file, boolean reverse, boolean leftSide){ + if(file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)){ + directions = parseCloudmadeRoute(points, file, OSMAND_ROUTER.equals(file.author), leftSide, 10); + if(reverse){ + // clear directions all turns should be recalculated + directions = null; + Collections.reverse(points); + } + } else { + // first of all check tracks + for (Track tr : file.tracks) { + for (TrkSegment tkSeg : tr.segments) { + for (WptPt pt : tkSeg.points) { + points.add(createLocation(pt)); + } + } + } + if (points.isEmpty()) { + for (Route rte : file.routes) { + for (WptPt pt : rte.points) { + points.add(createLocation(pt)); + } + } + } + if (reverse) { + Collections.reverse(points); + } + } + } + } + + private static Location createLocation(WptPt pt){ + Location loc = new Location("OsmandRouteProvider"); + loc.setLatitude(pt.lat); + loc.setLongitude(pt.lon); + loc.setSpeed((float) pt.speed); + if(!Double.isNaN(pt.ele)) { + loc.setAltitude(pt.ele); + } + loc.setTime(pt.time); + if(!Double.isNaN(pt.hdop)) { + loc.setAccuracy((float) pt.hdop); + } + return loc; + } + + + + + public RouteCalculationResult calculateRouteImpl(RouteCalculationParams params){ + long time = System.currentTimeMillis(); + if (params.start != null && params.end != null) { + if(log.isInfoEnabled()){ + log.info("Start finding route from " + params.start + " to " + params.end +" using " + + params.type.getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + try { + RouteCalculationResult res; + if(params.gpxRoute != null && !params.gpxRoute.points.isEmpty()){ + res = calculateGpxRoute(params); + } else if (params.type == RouteService.YOURS) { + res = findYOURSRoute(params); + } else if (params.type == RouteService.ORS) { + res = findORSRoute(params); + } else if (params.type == RouteService.OSMAND) { + res = findVectorMapsRoute(params); + } else { + res = findCloudMadeRoute(params); + } + if(log.isInfoEnabled() ){ + log.info("Finding route contained " + res.getImmutableLocations().size() + " points for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + return res; + } catch (IOException e) { + log.error("Failed to find route ", e); //$NON-NLS-1$ + } catch (ParserConfigurationException e) { + log.error("Failed to find route ", e); //$NON-NLS-1$ + } catch (SAXException e) { + log.error("Failed to find route ", e); //$NON-NLS-1$ + } + } + return new RouteCalculationResult(null); + } + + + private RouteCalculationResult calculateGpxRoute(RouteCalculationParams pars) { + RouteCalculationResult res; + // get the closest point to start and to end + float minDist = Integer.MAX_VALUE; + int startI = 0; + GPXRouteParams params = pars.gpxRoute; + List gpxRoute = params.points; + int endI = gpxRoute.size(); + if (pars.start != null) { + for (int i = 0; i < gpxRoute.size(); i++) { + float d = gpxRoute.get(i).distanceTo(pars.start); + if (d < minDist) { + startI = i; + minDist = d; + } + } + } else { + pars.start = gpxRoute.get(0); + } + Location l = new Location("temp"); //$NON-NLS-1$ + l.setLatitude(pars.end.getLatitude()); + l.setLongitude(pars.end.getLongitude()); + minDist = Integer.MAX_VALUE; + // get in reverse order taking into account ways with cycle + for (int i = gpxRoute.size() - 1; i >= startI; i--) { + float d = gpxRoute.get(i).distanceTo(l); + if (d < minDist) { + endI = i + 1; + // slightly modify to allow last point to be added + minDist = d - 40; + } + } + ArrayList sublist = new ArrayList(gpxRoute.subList(startI, endI)); + if(params.directions == null){ + res = new RouteCalculationResult(sublist, params.directions, pars.start, pars.end, null, null, + pars.ctx, pars.leftSide, true); + } else { + List subdirections = new ArrayList(); + for (RouteDirectionInfo info : params.directions) { + if(info.routePointOffset >= startI && info.routePointOffset < endI){ + RouteDirectionInfo ch = new RouteDirectionInfo(info.getAverageSpeed(), info.getTurnType()); + ch.routePointOffset = info.routePointOffset - startI; + ch.setDescriptionRoute(info.getDescriptionRoute()); + + // recalculate + ch.distance = 0; + ch.afterLeftTime = 0; + subdirections.add(ch); + } + } + res = new RouteCalculationResult(sublist, subdirections, pars.start, pars.end, null, null, + pars.ctx, pars.leftSide, true); + } + return res; + } + + protected String getString(ClientContext ctx, int resId){ + if(ctx == null){ + return ""; //$NON-NLS-1$ + } + return ctx.getString(resId); + } + + + + + protected RouteCalculationResult findYOURSRoute(RouteCalculationParams params) throws MalformedURLException, IOException, + ParserConfigurationException, FactoryConfigurationError, SAXException { + List res = new ArrayList(); + StringBuilder uri = new StringBuilder(); + uri.append("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml"); //$NON-NLS-1$ + uri.append("&flat=").append(params.start.getLatitude()); //$NON-NLS-1$ + uri.append("&flon=").append(params.start.getLongitude()); //$NON-NLS-1$ + uri.append("&tlat=").append(params.end.getLatitude()); //$NON-NLS-1$ + uri.append("&tlon=").append(params.end.getLongitude()); //$NON-NLS-1$ + if(ApplicationMode.PEDESTRIAN == params.mode){ + uri.append("&v=foot") ; //$NON-NLS-1$ + } else if(ApplicationMode.BICYCLE == params.mode){ + uri.append("&v=bicycle") ; //$NON-NLS-1$ + } else { + uri.append("&v=motorcar"); //$NON-NLS-1$ + } + uri.append("&fast=").append(params.fast ? "1" : "0").append("&layer=mapnik"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + log.info("URL route " + uri); + URL url = new URL(uri.toString()); + URLConnection connection = url.openConnection(); + DocumentBuilder dom = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = dom.parse(new InputSource(new InputStreamReader(connection.getInputStream()))); + NodeList list = doc.getElementsByTagName("coordinates"); //$NON-NLS-1$ + for(int i=0; i specs = new ArrayList(); + if (!settings.FAST_ROUTE_MODE.getModeValue(params.mode)) { + specs.add(GeneralRouter.USE_SHORTEST_WAY); + } + if(settings.AVOID_FERRIES.getModeValue(params.mode)){ + specs.add(GeneralRouter.AVOID_FERRIES); + } + if(settings.AVOID_TOLL_ROADS.getModeValue(params.mode)){ + specs.add(GeneralRouter.AVOID_TOLL); + } + if(settings.AVOID_MOTORWAY.getModeValue(params.mode)){ + specs.add(GeneralRouter.AVOID_MOTORWAY); + } else if(settings.PREFER_MOTORWAYS.getModeValue(params.mode)){ + specs.add(GeneralRouter.PREFER_MOTORWAYS); + } + if(settings.AVOID_UNPAVED_ROADS.getModeValue(params.mode)){ + specs.add(GeneralRouter.AVOID_UNPAVED); + } + String[] specialization = specs.toArray(new String[specs.size()]); + float mb = (1 << 20); + Runtime rt = Runtime.getRuntime(); + // make visible + int memoryLimit = (int) (0.95 * ((rt.maxMemory() - rt.totalMemory()) + rt.freeMemory()) / mb); + log.warn("Use " + memoryLimit + " MB Free " + rt.freeMemory() / mb + " of " + rt.totalMemory() / mb + " max " + rt.maxMemory() / mb); + + RoutingConfiguration cf = config.build(p.name().toLowerCase(), params.start.hasBearing() ? + params.start.getBearing() / 180d * Math.PI : null, + memoryLimit, specialization); + if(!params.optimal){ + cf.heuristicCoefficient *= 1.5; + // native use + cf.attributes.put("heuristicCoefficient", cf.heuristicCoefficient+""); + } + RoutingContext ctx = new RoutingContext(cf, params.ctx.getInternalAPI().getNativeLibrary(), files); + ctx.calculationProgress = params.calculationProgress; + if(params.previousToRecalculate != null) { + ctx.previouslyCalculatedRoute = params.previousToRecalculate.getOriginalRoute(); + } + LatLon st = new LatLon(params.start.getLatitude(), params.start.getLongitude()); + LatLon en = new LatLon(params.end.getLatitude(), params.end.getLongitude()); + List inters = new ArrayList(); + if (params.intermediates != null) { + inters = new ArrayList(params.intermediates); + } + try { + List result = router.searchRoute(ctx, st, en, inters, params.leftSide); + if(result == null || result.isEmpty()) { + if(ctx.calculationProgress.segmentNotFound == 0) { + return new RouteCalculationResult(params.ctx.getString(R.string.starting_point_too_far)); + } else if(ctx.calculationProgress.segmentNotFound == inters.size() + 1) { + return new RouteCalculationResult(params.ctx.getString(R.string.ending_point_too_far)); + } else if(ctx.calculationProgress.segmentNotFound > 0) { + return new RouteCalculationResult(params.ctx.getString(R.string.intermediate_point_too_far, "'" + ctx.calculationProgress.segmentNotFound + "'")); + } + if(ctx.calculationProgress.directSegmentQueueSize == 0) { + return new RouteCalculationResult("Route can not be found from start point (" +ctx.calculationProgress.distanceFromBegin/1000f+" km)"); + } else if(ctx.calculationProgress.reverseSegmentQueueSize == 0) { + return new RouteCalculationResult("Route can not be found from end point (" +ctx.calculationProgress.distanceFromEnd/1000f+" km)"); + } + if(ctx.calculationProgress.isCancelled) { + return new RouteCalculationResult("Route calculation was interrupted"); + } + // something really strange better to see that message on the scren + return new RouteCalculationResult("Empty result"); + } else { + RouteCalculationResult res = new RouteCalculationResult(result, params.start, params.end, + params.intermediates, params.ctx, params.leftSide, ctx.routingTime); + return res; + } + } catch (RuntimeException e) { + return new RouteCalculationResult(e.getMessage() ); + } catch (InterruptedException e) { + return new RouteCalculationResult("Route calculation was interrupted"); + } catch (OutOfMemoryError e) { +// ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE); +// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); +// activityManager.getMemoryInfo(memoryInfo); +// int avl = (int) (memoryInfo.availMem / (1 << 20)); + int max = (int) (Runtime.getRuntime().maxMemory() / (1 << 20)); + int avl = (int) (Runtime.getRuntime().freeMemory() / (1 << 20)); + String s = " (" + avl + " MB available of " + max + ") "; + return new RouteCalculationResult("Not enough process memory "+ s); + } + } + + + protected RouteCalculationResult findCloudMadeRoute(RouteCalculationParams params) + throws MalformedURLException, IOException, ParserConfigurationException, FactoryConfigurationError, SAXException { + List res = new ArrayList(); + List directions = null; + StringBuilder uri = new StringBuilder(); + // possibly hide that API key because it is privacy of osmand + // A6421860EBB04234AB5EF2D049F2CD8F key is compromised + uri.append("http://routes.cloudmade.com/A6421860EBB04234AB5EF2D049F2CD8F/api/0.3/"); //$NON-NLS-1$ + uri.append(params.start.getLatitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$ + uri.append(params.start.getLongitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$ + if(params.intermediates != null && params.intermediates.size() > 0) { + uri.append("["); + boolean first = true; + for(LatLon il : params.intermediates) { + if(!first){ + uri.append(","); + } else { + first = false; + } + uri.append(il.getLatitude() + "").append(","); //$NON-NLS-1$ //$NON-NLS-2$ + uri.append(il.getLongitude() + ""); //$NON-NLS-1$ //$NON-NLS-2$ + } + uri.append("],"); + } + uri.append(params.end.getLatitude() + "").append(","); //$NON-NLS-1$//$NON-NLS-2$ + uri.append(params.end.getLongitude() + "").append("/"); //$NON-NLS-1$ //$NON-NLS-2$ + + float speed = 1.5f; + if (ApplicationMode.PEDESTRIAN == params.mode) { + uri.append("foot.gpx"); //$NON-NLS-1$ + } else if (ApplicationMode.BICYCLE == params.mode) { + speed = 5.5f; + uri.append("bicycle.gpx"); //$NON-NLS-1$ + } else { + speed = 15.3f; + if (params.fast) { + uri.append("car.gpx"); //$NON-NLS-1$ + } else { + uri.append("car/shortest.gpx"); //$NON-NLS-1$ + } + } + uri.append("?lang=").append(Locale.getDefault().getLanguage()); //$NON-NLS-1$ + log.info("URL route " + uri); + URL url = new URL(uri.toString()); + URLConnection connection = url.openConnection(); + GPXFile gpxFile = GPXUtilities.loadGPXFile(params.ctx, connection.getInputStream(), false); + directions = parseCloudmadeRoute(res, gpxFile, false, params.leftSide, speed); + + return new RouteCalculationResult(res, directions, params.start, params.end, params.intermediates, + null, params.ctx, params.leftSide, true); + } + + private static List parseCloudmadeRoute(List res, GPXFile gpxFile, boolean osmandRouter, + boolean leftSide, float defSpeed) { + List directions = null; + if (!osmandRouter) { + for (WptPt pt : gpxFile.points) { + res.add(createLocation(pt)); + } + } else { + for (Track tr : gpxFile.tracks) { + for (TrkSegment ts : tr.segments) { + for (WptPt p : ts.points) { + res.add(createLocation(p)); + } + } + } + } + float[] distanceToEnd = new float[res.size()]; + for (int i = res.size() - 2; i >= 0; i--) { + distanceToEnd[i] = distanceToEnd[i + 1] + res.get(i).distanceTo(res.get(i + 1)); + } + + Route route = null; + if (gpxFile.routes.size() > 0) { + route = gpxFile.routes.get(0); + } + RouteDirectionInfo previous = null; + if (route != null && route.points.size() > 0) { + directions = new ArrayList(); + Iterator iterator = route.points.iterator(); + while(iterator.hasNext()){ + WptPt item = iterator.next(); + try { + String stime = item.getExtensionsToRead().get("time"); + int time = 0; + if (stime != null) { + time = Integer.parseInt(stime); + } + int offset = Integer.parseInt(item.getExtensionsToRead().get("offset")); //$NON-NLS-1$ + if(directions.size() > 0) { + RouteDirectionInfo last = directions.get(directions.size() - 1); + // update speed using time and idstance + last.setAverageSpeed((distanceToEnd[last.routePointOffset] - distanceToEnd[offset])/last.getAverageSpeed()); + last.distance = (int) (distanceToEnd[last.routePointOffset] - distanceToEnd[offset]); + } + // save time as a speed because we don't know distance of the route segment + float avgSpeed = time; + if(!iterator.hasNext() && time > 0) { + avgSpeed = distanceToEnd[offset] / time; + } + String stype = item.getExtensionsToRead().get("turn"); //$NON-NLS-1$ + TurnType turnType; + if (stype != null) { + turnType = TurnType.valueOf(stype.toUpperCase(), leftSide); + } else { + turnType = TurnType.valueOf(TurnType.C, leftSide); + } + String sturn = item.getExtensionsToRead().get("turn-angle"); //$NON-NLS-1$ + if (sturn != null) { + turnType.setTurnAngle((float) Double.parseDouble(sturn)); + } + RouteDirectionInfo dirInfo = new RouteDirectionInfo(avgSpeed, turnType); + dirInfo.setDescriptionRoute(item.desc); //$NON-NLS-1$ + dirInfo.routePointOffset = offset; + if (previous != null && !TurnType.C.equals(previous.getTurnType().getValue()) && + !osmandRouter) { + // calculate angle + if (previous.routePointOffset > 0) { + float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset)); + float caz; + if (previous.getTurnType().isRoundAbout() && dirInfo.routePointOffset < res.size() - 1) { + caz = res.get(dirInfo.routePointOffset).bearingTo(res.get(dirInfo.routePointOffset + 1)); + } else { + caz = res.get(dirInfo.routePointOffset - 1).bearingTo(res.get(dirInfo.routePointOffset)); + } + float angle = caz - paz; + if (angle < 0) { + angle += 360; + } else if (angle > 360) { + angle -= 360; + } + // that magic number helps to fix some errors for turn + angle += 75; + + if (previous.getTurnType().getTurnAngle() < 0.5f) { + previous.getTurnType().setTurnAngle(angle); + } + } + } + + directions.add(dirInfo); + + previous = dirInfo; + } catch (NumberFormatException e) { + log.info("Exception", e); //$NON-NLS-1$ + } catch (IllegalArgumentException e) { + log.info("Exception", e); //$NON-NLS-1$ + } + } + } + if (previous != null && !TurnType.C.equals(previous.getTurnType().getValue())) { + // calculate angle + if (previous.routePointOffset > 0 && previous.routePointOffset < res.size() - 1) { + float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset)); + float caz = res.get(previous.routePointOffset).bearingTo(res.get(res.size() - 1)); + float angle = caz - paz; + if (angle < 0) { + angle += 360; + } + if (previous.getTurnType().getTurnAngle() < 0.5f) { + previous.getTurnType().setTurnAngle(angle); + } + } + } + return directions; + } + + protected RouteCalculationResult findORSRoute(RouteCalculationParams params) throws MalformedURLException, IOException, ParserConfigurationException, FactoryConfigurationError, + SAXException { + List res = new ArrayList(); + + String rpref = "Fastest"; + if (ApplicationMode.PEDESTRIAN == params.mode) { + rpref = "Pedestrian"; + } else if (ApplicationMode.BICYCLE == params.mode) { + rpref = "Bicycle"; + // } else if (ApplicationMode.LOWTRAFFIC == mode) { + // rpref = "BicycleSafety"; + // } else if (ApplicationMode.RACEBIKE == mode) { + // rpref = "BicycleRacer"; + // } else if (ApplicationMode.TOURBIKE == mode) { + // rpref = "BicycleRoute"; + // } else if (ApplicationMode.MTBIKE == mode) { + // rpref = "BicycleMTB"; + } else if (!params.fast) { + rpref = "Shortest"; + } + + StringBuilder request = new StringBuilder(); + request.append("http://openls.geog.uni-heidelberg.de/osm/eu/routing?").append("start=").append(params.start.getLongitude()).append(',') + .append(params.start.getLatitude()).append("&end=").append(params.end.getLongitude()).append(',').append(params.end.getLatitude()) + .append("&preference=").append(rpref); + // TODO if we would get instructions from the service, we could use this language setting + // .append("&language=").append(Locale.getDefault().getLanguage()); + + log.info("URL route " + request.toString()); + URI uri = URI.create(request.toString()); + URL url = uri.toURL(); + URLConnection connection = url.openConnection(); + + DocumentBuilder dom = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = dom.parse(new InputSource(new InputStreamReader(connection.getInputStream()))); + NodeList list = doc.getElementsByTagName("xls:RouteGeometry"); //$NON-NLS-1$ + for (int i = 0; i < list.getLength(); i++) { + NodeList poslist = ((Element) list.item(i)).getElementsByTagName("gml:pos"); //$NON-NLS-1$ + for (int j = 0; j < poslist.getLength(); j++) { + String text = poslist.item(j).getFirstChild().getNodeValue(); + int s = text.indexOf(' '); + try { + double lon = Double.parseDouble(text.substring(0, s)); + double lat = Double.parseDouble(text.substring(s + 1)); + Location l = new Location("router"); //$NON-NLS-1$ + l.setLatitude(lat); + l.setLongitude(lon); + res.add(l); + } catch (NumberFormatException nfe) { + } + } + } + if (list.getLength() == 0) { + if (doc.getChildNodes().getLength() == 1) { + Node item = doc.getChildNodes().item(0); + return new RouteCalculationResult(item.getNodeValue()); + + } + } + return new RouteCalculationResult(res, null, params.start, params.end, null, null, params.ctx, params.leftSide, true); + } + + public GPXFile createOsmandRouterGPX(RouteCalculationResult srcRoute){ + int currentRoute = srcRoute.currentRoute; + List routeNodes = srcRoute.getImmutableLocations(); + List directionInfo = srcRoute.getDirections(); + int currentDirectionInfo = srcRoute.currentDirectionInfo; + + GPXFile gpx = new GPXFile(); + gpx.author = OSMAND_ROUTER; + Track track = new Track(); + gpx.tracks.add(track); + TrkSegment trkSegment = new TrkSegment(); + track.segments.add(trkSegment); + int cRoute = currentRoute; + int cDirInfo = currentDirectionInfo; + + for(int i = cRoute; i< routeNodes.size(); i++){ + Location loc = routeNodes.get(i); + WptPt pt = new WptPt(); + pt.lat = loc.getLatitude(); + pt.lon = loc.getLongitude(); + if(loc.hasSpeed()){ + pt.speed = loc.getSpeed(); + } + if(loc.hasAltitude()){ + pt.ele = loc.getAltitude(); + } + if(loc.hasAccuracy()){ + pt.hdop = loc.getAccuracy(); + } + trkSegment.points.add(pt); + } + Route route = new Route(); + gpx.routes.add(route); + for (int i = cDirInfo; i < directionInfo.size(); i++) { + RouteDirectionInfo dirInfo = directionInfo.get(i); + if (dirInfo.routePointOffset >= cRoute) { + Location loc = routeNodes.get(dirInfo.routePointOffset); + WptPt pt = new WptPt(); + pt.lat = loc.getLatitude(); + pt.lon = loc.getLongitude(); + pt.desc = dirInfo.getDescriptionRoute(); + Map extensions = pt.getExtensionsToWrite(); + extensions.put("time", dirInfo.getExpectedTime() + ""); + String turnType = dirInfo.getTurnType().getValue(); + if (dirInfo.getTurnType().isRoundAbout()) { + turnType += dirInfo.getTurnType().getExitOut(); + } + if(!TurnType.C.equals(turnType)){ + extensions.put("turn", turnType); + extensions.put("turn-angle", dirInfo.getTurnType().getTurnAngle() + ""); + } + extensions.put("offset", (dirInfo.routePointOffset - cRoute) + ""); + route.points.add(pt); + } + } + return gpx; + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd-java/src/net/osmand/plus/routing/RoutingHelper.java new file mode 100644 index 0000000000..95f08c6fe9 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/RoutingHelper.java @@ -0,0 +1,810 @@ +package net.osmand.plus.routing; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.osmand.Location; +import net.osmand.PlatformUtil; +import net.osmand.binary.RouteDataObject; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; +import net.osmand.data.LatLon; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.GPXUtilities.GPXFile; +import net.osmand.plus.ClientContext; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.OsmandSettings.MetricsConstants; +import net.osmand.plus.R; +import net.osmand.plus.TargetPointsHelper; +import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; +import net.osmand.plus.routing.RouteProvider.GPXRouteParams; +import net.osmand.plus.routing.RouteProvider.RouteService; +import net.osmand.plus.voice.CommandPlayer; +import net.osmand.router.RouteCalculationProgress; +import net.osmand.router.RouteSegmentResult; +import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; + +public class RoutingHelper { + + private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class); + + public static interface IRouteInformationListener { + + public void newRouteIsCalculated(boolean newRoute); + + public void routeWasCancelled(); + } + + private final float POSITION_TOLERANCE = 60; + + private List listeners = new ArrayList(); + + private ClientContext app; + + private boolean isFollowingMode = false; + + private GPXRouteParams currentGPXRoute = null; + + private RouteCalculationResult route = new RouteCalculationResult(""); + + private LatLon finalLocation; + private List intermediatePoints; + private Location lastProjection; + private Location lastFixedLocation; + + private Thread currentRunningJob; + private long lastTimeEvaluatedRoute = 0; + private int evalWaitInterval = 3000; + + private ApplicationMode mode; + private OsmandSettings settings; + + private RouteProvider provider = new RouteProvider(); + private VoiceRouter voiceRouter; + + private boolean makeUturnWhenPossible = false; + private long makeUTwpDetected = 0; + //private long wrongMovementDetected = 0; + + private RouteCalculationProgressCallback progressRoute; + +// private ProgressBar progress; +// private Handler progressHandler; + + + + public boolean makeUturnWhenPossible() { + return makeUturnWhenPossible; + } + + + public RoutingHelper(ClientContext context, CommandPlayer player){ + this.app = context; + settings = context.getSettings(); + voiceRouter = new VoiceRouter(this, player); + } + + public boolean isFollowingMode() { + return isFollowingMode; + } + + public void setFollowingMode(boolean follow) { + isFollowingMode = follow; + if(follow) { + if(!app.getInternalAPI().isNavigationServiceStarted()) { + app.getInternalAPI().startNavigationService(true); + } + } else { + if(app.getInternalAPI().isNavigationServiceStartedForNavigation()) { + app.getInternalAPI().stopNavigationService(); + } + } + } + + + + public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List intermediatePoints, Location currentLocation, GPXRouteParams gpxRoute){ + clearCurrentRoute(finalLocation, intermediatePoints); + currentGPXRoute = gpxRoute; + // to update route + setCurrentLocation(currentLocation, false); + + } + + public synchronized void clearCurrentRoute(LatLon newFinalLocation, List newIntermediatePoints) { + route = new RouteCalculationResult(""); + makeUturnWhenPossible = false; + evalWaitInterval = 3000; + app.runInUIThread(new Runnable() { + @Override + public void run() { + for (IRouteInformationListener l : listeners) { + l.routeWasCancelled(); + } + } + }); + this.finalLocation = newFinalLocation; + this.intermediatePoints = newIntermediatePoints; + if(currentRunningJob instanceof RouteRecalculationThread) { + ((RouteRecalculationThread) currentRunningJob).stopCalculation(); + } + if (newFinalLocation == null) { + settings.FOLLOW_THE_ROUTE.set(false); + settings.FOLLOW_THE_GPX_ROUTE.set(null); + // clear last fixed location + this.lastProjection = null; + setFollowingMode(false); + } + } + + public GPXRouteParams getCurrentGPXRoute() { + return currentGPXRoute; + } + + public List getCurrentRoute() { + return currentGPXRoute == null || currentGPXRoute.points.isEmpty() ? route.getImmutableLocations() : Collections + .unmodifiableList(currentGPXRoute.points); + } + + public void setAppMode(ApplicationMode mode){ + this.mode = mode; + voiceRouter.updateAppMode(); + } + + public ApplicationMode getAppMode() { + return mode; + } + + public LatLon getFinalLocation() { + return finalLocation; + } + + public List getIntermediatePoints() { + return intermediatePoints; + } + + public boolean isRouteCalculated(){ + return route.isCalculated(); + } + + public VoiceRouter getVoiceRouter() { + return voiceRouter; + } + + public Location getLastProjection(){ + return lastProjection; + } + + public void addListener(IRouteInformationListener l){ + listeners.add(l); + } + + public boolean removeListener(IRouteInformationListener l){ + return listeners.remove(l); + } + + public void updateLocation(Location currentLocation) { + if(isFollowingMode()) { + setCurrentLocation(currentLocation, false); + } + } + + + public Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation ) { + Location locationProjection = currentLocation; + if (finalLocation == null || currentLocation == null) { + makeUturnWhenPossible = false; + return locationProjection; + } + float posTolerance = POSITION_TOLERANCE; + if(currentLocation.hasAccuracy()) { + posTolerance = POSITION_TOLERANCE / 2 + currentLocation.getAccuracy(); + } + boolean calculateRoute = false; + synchronized (this) { + // 0. Route empty or needs to be extended? Then re-calculate route. + if(route.isEmpty()) { + calculateRoute = true; + } else { + // 1. Update current route position status according to latest received location + boolean finished = updateCurrentRouteStatus(currentLocation, posTolerance); + if (finished) { + return null; + } + List routeNodes = route.getImmutableLocations(); + int currentRoute = route.currentRoute; + + // 2. Analyze if we need to recalculate route + // >100m off current route (sideways) + if (currentRoute > 0) { + double dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute)); + if (dist > 1.7 * posTolerance) { + log.info("Recalculate route, because correlation : " + dist); //$NON-NLS-1$ + calculateRoute = true; + } + } + // 3. Identify wrong movement direction + Location next = route.getNextRouteLocation(); + boolean wrongMovementDirection = checkWrongMovementDirection(currentLocation, next); + if (wrongMovementDirection && currentLocation.distanceTo(routeNodes.get(currentRoute)) > 2 * posTolerance) { + log.info("Recalculate route, because wrong movement direction: " + currentLocation.distanceTo(routeNodes.get(currentRoute))); //$NON-NLS-1$ + calculateRoute = true; + } + // 4. Identify if UTurn is needed + boolean uTurnIsNeeded = identifyUTurnIsNeeded(currentLocation, posTolerance); + // 5. Update Voice router + boolean inRecalc = calculateRoute || isRouteBeingCalculated(); + if (!inRecalc && !uTurnIsNeeded && !wrongMovementDirection) { + voiceRouter.updateStatus(currentLocation, false); + } else if (uTurnIsNeeded) { + voiceRouter.makeUTStatus(); + } + + // calculate projection of current location + if (currentRoute > 0) { + locationProjection = new Location(currentLocation); + Location nextLocation = routeNodes.get(currentRoute); + LatLon project = getProject(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute)); + + locationProjection.setLatitude(project.getLatitude()); + locationProjection.setLongitude(project.getLongitude()); + // we need to update bearing too + float bearingTo = locationProjection.bearingTo(nextLocation); + locationProjection.setBearing(bearingTo); + } + } + lastFixedLocation = currentLocation; + lastProjection = locationProjection; + } + + if (calculateRoute) { + recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute, route.isCalculated() ? route + : null); + } + double projectDist = mode == ApplicationMode.CAR ? posTolerance : posTolerance / 2; + if(returnUpdatedLocation && locationProjection != null && currentLocation.distanceTo(locationProjection) < projectDist) { + return locationProjection; + } else { + return currentLocation; + } + } + + private static double getOrthogonalDistance(Location loc, Location from, Location to) { + return MapUtils.getOrthogonalDistance(loc.getLatitude(), + loc.getLongitude(), from.getLatitude(), from.getLongitude(), + to.getLatitude(), to.getLongitude()); + } + + private static LatLon getProject(Location loc, Location from, Location to) { + return MapUtils.getProjection(loc.getLatitude(), + loc.getLongitude(), from.getLatitude(), from.getLongitude(), + to.getLatitude(), to.getLongitude()); + } + + private static int lookAheadFindMinOrthogonalDistance(Location currentLocation, List routeNodes, int currentRoute, int iterations) { + double newDist; + double dist = Double.POSITIVE_INFINITY; + int index = currentRoute; + while (iterations > 0 && currentRoute + 1 < routeNodes.size()) { + newDist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute), routeNodes.get(currentRoute + 1)); + if (newDist < dist) { + index = currentRoute; + dist = newDist; + } + currentRoute++; + iterations--; + } + return index; + } + + private boolean updateCurrentRouteStatus(Location currentLocation, float posTolerance) { + List routeNodes = route.getImmutableLocations(); + int currentRoute = route.currentRoute; + // 1. Try to proceed to next point using orthogonal distance (finding minimum orthogonal dist) + while (currentRoute + 1 < routeNodes.size()) { + double dist = currentLocation.distanceTo(routeNodes.get(currentRoute)); + if(currentRoute > 0) { + dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), + routeNodes.get(currentRoute)); + } + boolean processed = false; + // if we are still too far try to proceed many points + // if not then look ahead only 3 in order to catch sharp turns + boolean longDistance = dist >= 250; + int newCurrentRoute = lookAheadFindMinOrthogonalDistance(currentLocation, routeNodes, currentRoute, longDistance ? 15 : 8); + double newDist = getOrthogonalDistance(currentLocation, routeNodes.get(newCurrentRoute), + routeNodes.get(newCurrentRoute + 1)); + if(longDistance) { + if(newDist < dist) { + if (log.isDebugEnabled()) { + log.debug("Processed by distance : (new) " + newDist + " (old) " + dist); //$NON-NLS-1$//$NON-NLS-2$ + } + processed = true; + } + } else if (newDist < dist || newDist < 10) { + // newDist < 10 (avoid distance 0 till next turn) + if (dist > posTolerance) { + processed = true; + if (log.isDebugEnabled()) { + log.debug("Processed by distance : " + newDist + " " + dist); //$NON-NLS-1$//$NON-NLS-2$ + } + } else { + // case if you are getting close to the next point after turn + // but you have not yet turned (could be checked bearing) + if (currentLocation.hasBearing() || lastFixedLocation != null) { + float bearingToRoute = currentLocation.bearingTo(routeNodes.get(currentRoute)); + float bearingRouteNext = routeNodes.get(newCurrentRoute).bearingTo(routeNodes.get(newCurrentRoute + 1)); + float bearingMotion = currentLocation.hasBearing() ? currentLocation.getBearing() : lastFixedLocation + .bearingTo(currentLocation); + double diff = Math.abs(MapUtils.degreesDiff(bearingMotion, bearingToRoute)); + double diffToNext = Math.abs(MapUtils.degreesDiff(bearingMotion, bearingRouteNext)); + if (diff > diffToNext) { + if (log.isDebugEnabled()) { + log.debug("Processed point bearing deltas : " + diff + " " + diffToNext); + } + processed = true; + } + } + } + } + if (processed) { + // that node already passed + route.updateCurrentRoute(newCurrentRoute + 1); + currentRoute = newCurrentRoute + 1; + } else { + break; + } + } + + // 2. check if intermediate found + if(route.getIntermediatePointsToPass() > 0 && route.getDistanceToNextIntermediate(lastFixedLocation) < POSITION_TOLERANCE * 2) { + showMessage(app.getString(R.string.arrived_at_intermediate_point)); + voiceRouter.arrivedIntermediatePoint(); + route.passIntermediatePoint(); + TargetPointsHelper targets = app.getInternalAPI().getTargetPointsHelper(); + int toDel = targets.getIntermediatePoints().size() - route.getIntermediatePointsToPass(); + while(toDel > 0) { + targets.removeWayPoint(false, 0); + toDel--; + } + while(intermediatePoints != null && route.getIntermediatePointsToPass() < intermediatePoints.size()) { + intermediatePoints.remove(0); + } + } + + // 3. check if destination found + Location lastPoint = routeNodes.get(routeNodes.size() - 1); + if (currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < POSITION_TOLERANCE * 1.5) { + showMessage(app.getString(R.string.arrived_at_destination)); + voiceRouter.arrivedDestinationPoint(); + clearCurrentRoute(null, null); + TargetPointsHelper targets = app.getInternalAPI().getTargetPointsHelper(); + targets.clearPointToNavigate(false); + return true; + } + return false; + } + + + public boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) { + if (finalLocation == null || currentLocation == null || !route.isCalculated()) { + this.makeUturnWhenPossible = false; + return makeUturnWhenPossible; + } + boolean makeUturnWhenPossible = false; + if (currentLocation.hasBearing()) { + float bearingMotion = currentLocation.getBearing() ; + Location nextRoutePosition = route.getNextRouteLocation(); + float bearingToRoute = currentLocation.bearingTo(nextRoutePosition); + double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute); + // 7. Check if you left the route and an unscheduled U-turn would bring you back (also Issue 863) + // This prompt is an interim advice and does only sound if a new route in forward direction could not be found in x seconds + if (Math.abs(diff) > 135f) { + float d = currentLocation.distanceTo(nextRoutePosition); + // 60m tolerance to allow for GPS inaccuracy + if (d > posTolerance) { + // require x sec continuous since first detection + if (makeUTwpDetected == 0) { + makeUTwpDetected = System.currentTimeMillis(); + } else if ((System.currentTimeMillis() - makeUTwpDetected > 10000)) { + makeUturnWhenPossible = true; + //log.info("bearingMotion is opposite to bearingRoute"); //$NON-NLS-1$ + } + } + } else { + makeUTwpDetected = 0; + } + } + this.makeUturnWhenPossible = makeUturnWhenPossible; + return makeUturnWhenPossible; + } + + /** + * Wrong movement direction is considered when between + * current location bearing (determines by 2 last fixed position or provided) + * and bearing from currentLocation to next (current) point + * the difference is more than 60 degrees + */ + public boolean checkWrongMovementDirection(Location currentLocation, Location nextRouteLocation) { + // measuring without bearing could be really error prone (with last fixed location) + // this code has an effect on route recalculation which should be detected without mistakes + if (currentLocation.hasBearing() && nextRouteLocation != null) { + float bearingMotion = currentLocation.getBearing(); + float bearingToRoute = currentLocation.bearingTo(nextRouteLocation); + double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute); + if (Math.abs(diff) > 60f) { + // require delay interval since first detection, to avoid false positive + //but leave out for now, as late detection is worse than false positive (it may reset voice router then cause bogus turn and u-turn prompting) + //if (wrongMovementDetected == 0) { + // wrongMovementDetected = System.currentTimeMillis(); + //} else if ((System.currentTimeMillis() - wrongMovementDetected > 500)) { + return true; + //} + } else { + //wrongMovementDetected = 0; + return false; + } + } + //wrongMovementDetected = 0; + return false; + } + + private synchronized void setNewRoute(RouteCalculationResult res, Location start){ + final boolean newRoute = !this.route.isCalculated(); + route = res; + if (isFollowingMode) { + if(lastFixedLocation != null) { + start = lastFixedLocation; + } + // try remove false route-recalculated prompts by checking direction to second route node + boolean wrongMovementDirection = false; + List routeNodes = res.getImmutableLocations(); + if (routeNodes != null && !routeNodes.isEmpty()) { + int newCurrentRoute = lookAheadFindMinOrthogonalDistance(start, routeNodes, res.currentRoute, 15); + if (newCurrentRoute + 1 < routeNodes.size()) { + // This check is valid for Online/GPX services (offline routing is aware of route direction) + wrongMovementDirection = checkWrongMovementDirection(start, routeNodes.get(newCurrentRoute + 1)); + // set/reset evalWaitInterval only if new route is in forward direction + if (!wrongMovementDirection) { + evalWaitInterval = 3000; + } else { + evalWaitInterval = evalWaitInterval * 3 / 2; + evalWaitInterval = Math.min(evalWaitInterval, 120000); + } + } + } + + + // trigger voice prompt only if new route is in forward direction + // If route is in wrong direction after one more setLocation it will be recalculated + if (!wrongMovementDirection || newRoute) { + voiceRouter.newRouteIsCalculated(newRoute); + } + } + + app.runInUIThread(new Runnable() { + @Override + public void run() { + for (IRouteInformationListener l : listeners) { + l.newRouteIsCalculated(newRoute); + } + } + }); + + } + + public synchronized int getLeftDistance(){ + return route.getDistanceToFinish(lastFixedLocation); + } + + public synchronized int getLeftDistanceNextIntermediate() { + return route.getDistanceToNextIntermediate(lastFixedLocation); + } + + public synchronized int getLeftTime() { + return route.getLeftTime(lastFixedLocation); + } + + public String getGeneralRouteInformation(){ + int dist = getLeftDistance(); + int hours = getLeftTime() / (60 * 60); + int minutes = (getLeftTime() / 60) % 60; + return app.getString(R.string.route_general_information, OsmAndFormatter.getFormattedDistance(dist, app), + hours, minutes); + } + + public Location getLocationFromRouteDirection(RouteDirectionInfo i){ + return route.getLocationFromRouteDirection(i); + } + + public synchronized NextDirectionInfo getNextRouteDirectionInfo(NextDirectionInfo info, boolean toSpeak){ + NextDirectionInfo i = route.getNextRouteDirectionInfo(info, lastProjection, toSpeak); + if(i != null) { + i.imminent = voiceRouter.calculateImminent(i.distanceTo, lastProjection); + } + return i; + } + + public synchronized float getCurrentMaxSpeed() { + return route.getCurrentMaxSpeed(); + } + + public synchronized AlarmInfo getMostImportantAlarm(MetricsConstants mc, boolean showCameras){ + float mxspeed = route.getCurrentMaxSpeed(); + AlarmInfo speedAlarm = createSpeedAlarm(mc, mxspeed, lastProjection); + AlarmInfo alarm = route.getMostImportantAlarm(lastProjection, speedAlarm, showCameras); + if(alarm != null) { +// voiceRouter.announceAlarm(alarm); + } + return alarm; + + } + + public static AlarmInfo calculateMostImportantAlarm(RouteDataObject ro, Location loc, + MetricsConstants mc, boolean showCameras) { + float mxspeed = ro.getMaximumSpeed(); + AlarmInfo speedAlarm = createSpeedAlarm(mc, mxspeed, loc); + if (speedAlarm != null) { +// voiceRouter.announceAlarm(speedAlarm); + return speedAlarm; + } + for (int i = 0; i < ro.getPointsLength(); i++) { + int[] pointTypes = ro.getPointTypes(i); + RouteRegion reg = ro.region; + if (pointTypes != null) { + for (int r = 0; r < pointTypes.length; r++) { + RouteTypeRule typeRule = reg.quickGetEncodingRule(pointTypes[r]); + AlarmInfo info = AlarmInfo.createAlarmInfo(typeRule, 0); + if (info != null) { + if (info.getType() != AlarmInfo.SPEED_CAMERA || showCameras) { +// voiceRouter.announceAlarm(info); + return info; + } + } + } + } + } + return null; + } + + + private static AlarmInfo createSpeedAlarm(MetricsConstants mc, float mxspeed, Location loc) { + AlarmInfo speedAlarm = null; + if (mxspeed != 0 && loc != null && loc.hasSpeed() && mxspeed != RouteDataObject.NONE_MAX_SPEED) { + float delta = 5f / 3.6f; + if (loc.getSpeed() > mxspeed + delta) { + int speed; + if (mc == MetricsConstants.KILOMETERS_AND_METERS) { + speed = Math.round(mxspeed * 3.6f); + } else { + speed = Math.round(mxspeed * 3.6f / 1.6f); + } + speedAlarm = AlarmInfo.createSpeedLimit(speed); + } + } + return speedAlarm; + } + + public static String formatStreetName(String name, String ref, String destination) { + if(destination != null && destination.length() > 0){ + if(ref != null && ref.length() > 0) { + destination = ref + " " + destination; + } + return destination; + } else if(name != null && name.length() > 0){ + if(ref != null && ref.length() > 0) { + name = ref + " " + name; + } + return name; + } else { + return ref; + } + } + + public synchronized String getCurrentName(){ + NextDirectionInfo n = getNextRouteDirectionInfo(new NextDirectionInfo(), false); + if((n.imminent == 0 || n.imminent == 1) && (n.directionInfo != null)) { + String nm = n.directionInfo.getStreetName(); + String rf = n.directionInfo.getRef(); + String dn = n.directionInfo.getDestinationName(); + return formatStreetName(nm, rf, dn); + } + RouteSegmentResult rs = route.getCurrentSegmentResult(); + if(rs != null) { + String nm = rs.getObject().getName(); + String rf = rs.getObject().getRef(); + String dn = rs.getObject().getDestinationName(); + return formatStreetName(nm, rf, dn); + } + return null; + } + + public synchronized NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo previous, NextDirectionInfo to, boolean toSpeak){ + NextDirectionInfo i = route.getNextRouteDirectionInfoAfter(previous, to, toSpeak); + if(i != null) { + i.imminent = voiceRouter.calculateImminent(i.distanceTo, null); + } + return i; + } + + public List getRouteDirections(){ + return route.getRouteDirections(); + } + + + + private class RouteRecalculationThread extends Thread { + + private final RouteCalculationParams params; + + public RouteRecalculationThread(String name, RouteCalculationParams params) { + super(name); + this.params = params; + if(params.calculationProgress == null) { + params.calculationProgress = new RouteCalculationProgress(); + } + } + + public void stopCalculation(){ + params.calculationProgress.isCancelled = true; + } + + + @Override + public void run() { + + RouteCalculationResult res = provider.calculateRouteImpl(params); + if (params.calculationProgress.isCancelled) { + currentRunningJob = null; + return; + } + + synchronized (RoutingHelper.this) { + if (res.isCalculated()) { + setNewRoute(res, params.start); + } else { + evalWaitInterval = evalWaitInterval * 3 / 2; + evalWaitInterval = Math.min(evalWaitInterval, 120000); + } + currentRunningJob = null; + } + + if (res.isCalculated()) { + String msg = app.getString(R.string.new_route_calculated_dist) + ": " + + OsmAndFormatter.getFormattedDistance(res.getWholeDistance(), app); + if (res.getRoutingTime() != 0f) { + msg += " (" + Algorithms.formatDuration((int) res.getRoutingTime()) + ")"; + } + showMessage(msg); + } else if (params.type != RouteService.OSMAND && !settings.isInternetConnectionAvailable()) { + showMessage(app.getString(R.string.error_calculating_route) + + ":\n" + app.getString(R.string.internet_connection_required_for_online_route)); //$NON-NLS-1$ + } else { + if (res.getErrorMessage() != null) { + showMessage(app.getString(R.string.error_calculating_route) + ":\n" + res.getErrorMessage()); //$NON-NLS-1$ + } else { + showMessage(app.getString(R.string.empty_route_calculated)); + } + } + lastTimeEvaluatedRoute = System.currentTimeMillis(); + } + + } + + private void recalculateRouteInBackground(final Location start, final LatLon end, final List intermediates, final GPXRouteParams gpxRoute, final RouteCalculationResult previousRoute){ + if (start == null || end == null) { + return; + } + if(currentRunningJob == null){ + // do not evaluate very often + if (System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) { + RouteCalculationParams params = new RouteCalculationParams(); + params.start = start; + params.end = end; + params.intermediates = intermediates; + params.gpxRoute = gpxRoute; + params.previousToRecalculate = previousRoute; + params.leftSide = settings.LEFT_SIDE_NAVIGATION.get(); + params.preciseRouting = settings.PRECISE_ROUTING_MODE.getModeValue(mode); + params.optimal = settings.OPTIMAL_ROUTE_MODE.getModeValue(mode); + params.fast = settings.FAST_ROUTE_MODE.getModeValue(mode); + params.type = settings.ROUTER_SERVICE.getModeValue(mode); + params.mode = mode; + params.ctx = app; + if(previousRoute == null && params.type == RouteService.OSMAND) { + params.calculationProgress = new RouteCalculationProgress(); + updateProgress(params.calculationProgress); + } + synchronized (this) { + currentRunningJob = new RouteRecalculationThread("Calculating route", params); //$NON-NLS-1$ + currentRunningJob.start(); + } + } + } + } + + public Thread startTaskInRouteThreadIfPossible(final Runnable r) { + if(currentRunningJob == null) { + synchronized (this) { + currentRunningJob = new Thread(new Runnable() { + @Override + public void run() { + try { + r.run(); + } finally { + synchronized (RoutingHelper.this) { + currentRunningJob = null; + } + } + } + }, "Calculating position"); //$NON-NLS-1$ + currentRunningJob.start(); + } + } + return currentRunningJob; + } + + + private void updateProgress(final RouteCalculationProgress calculationProgress) { + if(progressRoute != null) { + app.runInUIThread(new Runnable() { + @Override + public void run() { + if (isRouteBeingCalculated()) { + float p = calculationProgress.distanceFromBegin + calculationProgress.distanceFromEnd; + float all = calculationProgress.totalEstimatedDistance * 1.5f; + if (all > 0) { + int t = (int) Math.min(p * p / (all * all) * 100f, 99); + progressRoute.updateProgress(t); + } + updateProgress(calculationProgress); + } else { + progressRoute.finish(); + } + } + }, 300); + } + } + + public void setProgressBar(RouteCalculationProgressCallback progressRoute) { + this.progressRoute = progressRoute; + } + + public interface RouteCalculationProgressCallback { + + // set visibility + public void updateProgress(int progress); + + public void finish(); + + } + + + public boolean isRouteBeingCalculated(){ + return currentRunningJob instanceof RouteRecalculationThread; + } + + private void showMessage(final String msg){ + app.runInUIThread(new Runnable() { + @Override + public void run() { + app.showToastMessage(msg); + } + }); + } + + + // NEVER returns null + public RouteCalculationResult getRoute() { + return route; + } + + public GPXFile generateGPXFileWithRoute(){ + return provider.createOsmandRouterGPX(route); + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/routing/VoiceRouter.java b/OsmAnd-java/src/net/osmand/plus/routing/VoiceRouter.java new file mode 100644 index 0000000000..c84d05e6c3 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/routing/VoiceRouter.java @@ -0,0 +1,519 @@ +package net.osmand.plus.routing; + + +import net.osmand.Location; +import net.osmand.plus.ApplicationMode; +import net.osmand.plus.ClientContext; +import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; +import net.osmand.plus.voice.AbstractPrologCommandPlayer; +import net.osmand.plus.voice.CommandBuilder; +import net.osmand.plus.voice.CommandPlayer; +import net.osmand.router.TurnType; + + +public class VoiceRouter { + private final int STATUS_UTWP_TOLD = -1; + private final int STATUS_UNKNOWN = 0; + private final int STATUS_LONG_PREPARE = 1; + private final int STATUS_PREPARE = 2; + private final int STATUS_TURN_IN = 3; + private final int STATUS_TURN = 4; + private final int STATUS_TOLD = 5; + + private final RoutingHelper router; + private boolean mute = false; + private CommandPlayer player; + + + private int currentStatus = STATUS_UNKNOWN; + private float playGoAheadDist = 0; + + // private long lastTimeRouteRecalcAnnounced = 0; + + // default speed to have comfortable announcements (if actual speed is higher than it would be problem) + // Speed in m/s + protected float DEFAULT_SPEED = 12; + protected float TURN_DEFAULT_SPEED = 5; + + protected int PREPARE_LONG_DISTANCE = 0; + protected int PREPARE_LONG_DISTANCE_END = 0; + protected int PREPARE_DISTANCE = 0; + protected int PREPARE_DISTANCE_END = 0; + protected int TURN_IN_DISTANCE = 0; + protected int TURN_IN_DISTANCE_END = 0; + protected int TURN_DISTANCE = 0; + + protected VoiceCommandPending pendingCommand = null; + private RouteDirectionInfo nextRouteDirection; + + + public VoiceRouter(RoutingHelper router, CommandPlayer player) { + this.router = router; + this.player = player; + updateAppMode(); + } + + public void setPlayer(CommandPlayer player) { + this.player = player; + if(pendingCommand != null && player != null){ + CommandBuilder newCommand = getNewCommandPlayerToPlay(); + if (newCommand != null) { + pendingCommand.play(newCommand); + } + pendingCommand = null; + } + } + + public CommandPlayer getPlayer() { + return player; + } + + public void setMute(boolean mute) { + this.mute = mute; + } + + public boolean isMute() { + return mute; + } + + + protected CommandBuilder getNewCommandPlayerToPlay(){ + if(player == null || mute){ + return null; + } + return player.newCommandBuilder(); + } + + + + public void updateAppMode(){ + // turn prompt starts either at distance, or if actual-lead-time(currentSpeed) < maximum-lead-time + // lead time criterion only for TURN_IN and TURN + PREPARE_LONG_DISTANCE = 3500; // (105 sec) - 120 km/h + PREPARE_LONG_DISTANCE_END = 3000; // (90 sec) - 120 km/h + if(router.getAppMode() == ApplicationMode.PEDESTRIAN){ + // prepare distance is not needed for pedestrian + PREPARE_DISTANCE = 200; //(100 sec) + PREPARE_DISTANCE_END = 150 + 100; //( 75 sec) + not play + TURN_IN_DISTANCE = 100; // 50 sec + TURN_IN_DISTANCE_END = 70; // 35 sec + TURN_DISTANCE = 25; // 12 sec + TURN_DEFAULT_SPEED = DEFAULT_SPEED = 2f; // 7,2 km/h + } else if(router.getAppMode() == ApplicationMode.BICYCLE){ + PREPARE_DISTANCE = 500; //(100 sec) + PREPARE_DISTANCE_END = 350; //( 70 sec) + TURN_IN_DISTANCE = 225; // 45 sec + TURN_IN_DISTANCE_END = 80; // 16 sec + TURN_DISTANCE = 45; // 9 sec + TURN_DEFAULT_SPEED = DEFAULT_SPEED = 5; // 18 km/h + } else { + PREPARE_DISTANCE = 1500; //(125 sec) + PREPARE_DISTANCE_END = 1200;//(100 sec) + TURN_IN_DISTANCE = 390; // 30 sec + TURN_IN_DISTANCE_END = 182; // 14 sec + TURN_DISTANCE = 50; // 7 sec + TURN_DEFAULT_SPEED = 7f; // 25 km/h + DEFAULT_SPEED = 13; // 48 km/h + } + } + + protected boolean isDistanceLess(float currentSpeed, double dist, double etalon){ + if(dist < etalon || ((dist / currentSpeed) < (etalon / DEFAULT_SPEED))){ + return true; + } + return false; + } + + protected boolean isDistanceLess(float currentSpeed, double dist, double etalon, double defSpeed){ + if(dist < etalon || ((dist / currentSpeed) < (etalon / defSpeed))){ + return true; + } + return false; + } + + public int calculateImminent(float dist, Location loc){ + float speed = DEFAULT_SPEED; + if(loc != null && loc.hasSpeed()) { + speed = loc.getSpeed(); + } + if (isDistanceLess(speed, dist, TURN_IN_DISTANCE_END)) { + return 0; + } else if ( dist <= PREPARE_DISTANCE) { + return 1; + } else if (dist <= PREPARE_LONG_DISTANCE) { + return 2; + } else { + return -1; + } + } + + + private void nextStatusAfter(int previousStatus){ + //STATUS_UNKNOWN=0 -> STATUS_LONG_PREPARE=1 -> STATUS_PREPARE=2 -> STATUS_TURN_IN=3 -> STATUS_TURN=4 -> STATUS_TOLD=5 + if(previousStatus != STATUS_TOLD){ + this.currentStatus = previousStatus + 1; + } else { + this.currentStatus = previousStatus; + } + } + + private boolean statusNotPassed(int statusToCheck){ + return currentStatus <= statusToCheck; + } + + protected void makeUTStatus() { + // Mechanism via STATUS_UTWP_TOLD: Until turn in the right direction, or route is re-calculated in forward direction + if (currentStatus != STATUS_UTWP_TOLD) { + if (playMakeUTwp()) { + currentStatus = STATUS_UTWP_TOLD; + playGoAheadDist = 0; + } + } + + } + + /** + * Updates status of voice guidance + * @param currentLocation + */ + protected void updateStatus(Location currentLocation, boolean repeat) { + // Directly after turn: goAhead (dist), unless: + // < PREPARE_LONG_DISTANCE (3000m): playPrepareTurn + // < PREPARE_DISTANCE (1500m): playPrepareTurn + // < TURN_IN_DISTANCE (300m or 25sec): playMakeTurnIn + // < TURN_DISTANCE (60m or 5sec): playMakeTurn + float speed = DEFAULT_SPEED; + if (currentLocation != null && currentLocation.hasSpeed()) { + speed = Math.max(currentLocation.getSpeed(), speed); + } + + + NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new NextDirectionInfo(), true); + // after last turn say: + if (nextInfo == null || nextInfo.directionInfo == null || nextInfo.directionInfo.distance == 0) { + // if(currentStatus <= STATUS_UNKNOWN && currentDirection > 0){ This caused this prompt to be suppressed when coming back from a + if (repeat || currentStatus <= STATUS_UNKNOWN) { + if (playGoAheadToDestination()) { + currentStatus = STATUS_TOLD; + playGoAheadDist = 0; + } + } + return; + } + if(nextInfo.intermediatePoint){ + if (repeat || currentStatus <= STATUS_UNKNOWN) { + if (playGoAheadToIntermediate()) { + currentStatus = STATUS_TOLD; + playGoAheadDist = 0; + } + } + return; + } + int dist = nextInfo.distanceTo; + RouteDirectionInfo next = nextInfo.directionInfo; + + // if routing is changed update status to unknown + if (next != nextRouteDirection) { + nextRouteDirection = next; + currentStatus = STATUS_UNKNOWN; + playGoAheadDist = 0; + } + + if (!repeat && (dist == 0 || currentStatus == STATUS_TOLD)) { + // nothing said possibly that's wrong case we should say before that + // however it should be checked manually ? + return; + } + // say how much to go if there is next turn is a bit far + if (currentStatus == STATUS_UNKNOWN) { + if (!isDistanceLess(speed, dist, TURN_IN_DISTANCE * 1.3)) { + playGoAheadDist = dist - 80; + } + // say long distance message only for long distances > 10 km + // if (dist >= PREPARE_LONG_DISTANCE && !isDistanceLess(speed, dist, PREPARE_LONG_DISTANCE)) { + if (dist > PREPARE_LONG_DISTANCE + 300) { + nextStatusAfter(STATUS_UNKNOWN); + } else if (dist > PREPARE_DISTANCE + 300) { + // say prepare message if it is far enough and don't say preare long distance + nextStatusAfter(STATUS_LONG_PREPARE); + } else { + // don't say even prepare message + nextStatusAfter(STATUS_PREPARE); + } + } + + NextDirectionInfo nextNextInfo = router.getNextRouteDirectionInfoAfter(nextInfo, new NextDirectionInfo(), !repeat); + if ((repeat || statusNotPassed(STATUS_TURN)) && isDistanceLess(speed, dist, TURN_DISTANCE, TURN_DEFAULT_SPEED)) { + if (next.distance < TURN_IN_DISTANCE_END && nextNextInfo != null) { + playMakeTurn(next, nextNextInfo.directionInfo); + } else { + playMakeTurn(next, null); + } + nextStatusAfter(STATUS_TURN); + } else if ((repeat || statusNotPassed(STATUS_TURN_IN)) && isDistanceLess(speed, dist, TURN_IN_DISTANCE)) { + if (repeat || dist >= TURN_IN_DISTANCE_END) { + if ((isDistanceLess(speed, next.distance, TURN_DISTANCE) || next.distance < TURN_IN_DISTANCE_END) && + nextNextInfo != null) { + playMakeTurnIn(next, dist, nextNextInfo.directionInfo); + } else { + playMakeTurnIn(next, dist, null); + } + } + nextStatusAfter(STATUS_TURN_IN); + // } else if (statusNotPassed(STATUS_PREPARE) && isDistanceLess(speed, dist, PREPARE_DISTANCE)) { + } else if ((repeat || statusNotPassed(STATUS_PREPARE)) && (dist <= PREPARE_DISTANCE)) { + if (repeat || dist >= PREPARE_DISTANCE_END) { + if (!repeat && (next.getTurnType().keepLeft() || next.getTurnType().keepRight())){ + // do not play prepare for keep left/right + } else { + playPrepareTurn(next, dist); + } + } + nextStatusAfter(STATUS_PREPARE); + // } else if (statusNotPassed(STATUS_LONG_PREPARE) && isDistanceLess(speed, dist, PREPARE_LONG_DISTANCE)){ + } else if ((repeat || statusNotPassed(STATUS_LONG_PREPARE)) && (dist <= PREPARE_LONG_DISTANCE)) { + if (repeat || dist >= PREPARE_LONG_DISTANCE_END) { + playPrepareTurn(next, dist); + } + nextStatusAfter(STATUS_LONG_PREPARE); + } else if (statusNotPassed(STATUS_UNKNOWN)) { + // strange how we get here but + nextStatusAfter(STATUS_UNKNOWN); + } else if (repeat || (statusNotPassed(STATUS_TURN_IN) && dist < playGoAheadDist)) { + playGoAheadDist = 0; + playGoAhead(dist); + } + } + + public void announceCurrentDirection(Location currentLocation) { + synchronized (router) { + if (currentStatus != STATUS_UTWP_TOLD) { + updateStatus(currentLocation, true); + } else if (playMakeUTwp()) { + playGoAheadDist = 0; + } + } + } + + + private boolean playGoAheadToDestination() { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.goAhead(router.getLeftDistance()).andArriveAtDestination().play(); + return true; + } + return false; + } + + private boolean playGoAheadToIntermediate() { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.goAhead(router.getLeftDistanceNextIntermediate()).andArriveAtIntermediatePoint().play(); + return true; + } + return false; + } + + private boolean playMakeUTwp() { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.makeUTwp().play(); + return true; + } + return false; + } + + private void playGoAhead(int dist) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.goAhead(dist).play(); + } + } + + private void playPrepareTurn(RouteDirectionInfo next, int dist) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + String tParam = getTurnType(next.getTurnType()); + if(tParam != null){ + play.prepareTurn(tParam, dist).play(); + } else if(next.getTurnType().isRoundAbout()){ + play.prepareRoundAbout(dist).play(); + } else if(next.getTurnType().getValue().equals(TurnType.TU) || next.getTurnType().getValue().equals(TurnType.TRU)){ + play.prepareMakeUT(dist).play(); + } + } + } + + private void playMakeTurnIn(RouteDirectionInfo next, int dist, RouteDirectionInfo pronounceNextNext) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if (play != null) { + String tParam = getTurnType(next.getTurnType()); + boolean isPlay = true; + if (tParam != null) { + play.turn(tParam, dist); + } else if (next.getTurnType().isRoundAbout()) { + play.roundAbout(dist, next.getTurnType().getTurnAngle(), next.getTurnType().getExitOut()); + } else if (next.getTurnType().getValue().equals(TurnType.TU) || next.getTurnType().getValue().equals(TurnType.TRU)) { + play.makeUT(dist); + } else { + isPlay = false; + } + // small preparation to next after next + if (pronounceNextNext != null) { + TurnType t = pronounceNextNext.getTurnType(); + isPlay = true; + if (next.getTurnType().getValue().equals(TurnType.C) && + !TurnType.C.equals(t.getValue())) { + play.goAhead(dist); + } + if (TurnType.TL.equals(t.getValue()) || TurnType.TSHL.equals(t.getValue()) || TurnType.TSLL.equals(t.getValue()) + || TurnType.TU.equals(t.getValue()) || TurnType.KL.equals(t.getValue())) { + play.then().bearLeft(); + } else if (TurnType.TR.equals(t.getValue()) || TurnType.TSHR.equals(t.getValue()) || TurnType.TSLR.equals(t.getValue()) + || TurnType.KR.equals(t.getValue())) { + play.then().bearRight(); + } + } + if(isPlay){ + play.play(); + } + } + } + + private void playMakeTurn(RouteDirectionInfo next, RouteDirectionInfo nextNext) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + String tParam = getTurnType(next.getTurnType()); + boolean isplay = true; + if(tParam != null){ + play.turn(tParam); + } else if(next.getTurnType().isRoundAbout()){ + play.roundAbout(next.getTurnType().getTurnAngle(), next.getTurnType().getExitOut()); + } else if(next.getTurnType().getValue().equals(TurnType.TU) || next.getTurnType().getValue().equals(TurnType.TRU)){ + play.makeUT(); + // do not say it +// } else if(next.getTurnType().getValue().equals(TurnType.C)){ +// play.goAhead(); + } else { + isplay = false; + } + // add turn after next + if (nextNext != null) { + String t2Param = getTurnType(nextNext.getTurnType()); + if (t2Param != null) { + if(isplay) { play.then(); } + play.turn(t2Param, next.distance); + } else if (nextNext.getTurnType().isRoundAbout()) { + if(isplay) { play.then(); } + play.roundAbout(next.distance, nextNext.getTurnType().getTurnAngle(), nextNext.getTurnType().getExitOut()); + } else if (nextNext.getTurnType().getValue().equals(TurnType.TU)) { + if(isplay) { play.then(); } + play.makeUT(next.distance); + } + isplay = true; + } + if(isplay){ + play.play(); + } + } + } + + private String getTurnType(TurnType t){ + if(TurnType.TL.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_LEFT; + } else if(TurnType.TSHL.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_LEFT_SH; + } else if(TurnType.TSLL.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_LEFT_SL; + } else if(TurnType.TR.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_RIGHT; + } else if(TurnType.TSHR.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_RIGHT_SH; + } else if(TurnType.TSLR.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_RIGHT_SL; + } else if(TurnType.KL.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_LEFT_KEEP; + } else if(TurnType.KR.equals(t.getValue())){ + return AbstractPrologCommandPlayer.A_RIGHT_KEEP; + } + return null; + } + + public void gpsLocationLost(){ + CommandBuilder play = getNewCommandPlayerToPlay(); + if (play != null) { + play.gpsLocationLost().play(); + } + } + + public void newRouteIsCalculated(boolean newRoute) { + CommandBuilder play = getNewCommandPlayerToPlay(); + if (play != null) { + if (!newRoute) { + // suppress "route recalculated" prompt for GPX-routing, it makes no sense + // suppress "route recalculated" prompt for 60sec (this workaround now outdated after more intelligent route recalculation and directional voice prompt suppression) + // if (router.getCurrentGPXRoute() == null && (System.currentTimeMillis() - lastTimeRouteRecalcAnnounced > 60000)) { + if (router.getCurrentGPXRoute() == null) { + play.routeRecalculated(router.getLeftDistance()).play(); + currentStatus = STATUS_UNKNOWN; + // lastTimeRouteRecalcAnnounced = System.currentTimeMillis(); + } + } else { + play.newRouteCalculated(router.getLeftDistance()).play(); + currentStatus = STATUS_UNKNOWN; + } + } else if (player == null) { + pendingCommand = new VoiceCommandPending(!newRoute ? VoiceCommandPending.ROUTE_RECALCULATED + : VoiceCommandPending.ROUTE_CALCULATED, this); + currentStatus = STATUS_UNKNOWN; + } + nextRouteDirection = null; + } + + public void arrivedDestinationPoint() { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.arrivedAtDestination().play(); + } + } + + public void arrivedIntermediatePoint() { + CommandBuilder play = getNewCommandPlayerToPlay(); + if(play != null){ + play.arrivedAtIntermediatePoint().play(); + } + } + + public void onApplicationTerminate(ClientContext ctx) { + if (player != null) { + player.clear(); + } + } + + /** + * Command to wait until voice player is initialized + */ + private class VoiceCommandPending { + public static final int ROUTE_CALCULATED = 1; + public static final int ROUTE_RECALCULATED = 2; + protected final int type; + private final VoiceRouter voiceRouter; + + public VoiceCommandPending(int type, VoiceRouter voiceRouter){ + this.type = type; + this.voiceRouter = voiceRouter; + } + + public void play(CommandBuilder newCommand) { + int left = voiceRouter.router.getLeftDistance(); + if (left > 0) { + if (type == ROUTE_CALCULATED) { + newCommand.newRouteCalculated(left).play(); + } else if (type == ROUTE_RECALCULATED) { + newCommand.routeRecalculated(left).play(); + } + } + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java b/OsmAnd-java/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java new file mode 100644 index 0000000000..df4abf1109 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/voice/AbstractPrologCommandPlayer.java @@ -0,0 +1,214 @@ +package net.osmand.plus.voice; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.plus.ClientContext; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.OsmandSettings.MetricsConstants; +import net.osmand.plus.R; +import net.osmand.plus.api.ExternalServiceAPI.AudioFocusHelper; + +import org.apache.commons.logging.Log; + +import alice.tuprolog.InvalidLibraryException; +import alice.tuprolog.InvalidTheoryException; +import alice.tuprolog.NoSolutionException; +import alice.tuprolog.Number; +import alice.tuprolog.Prolog; +import alice.tuprolog.SolveInfo; +import alice.tuprolog.Struct; +import alice.tuprolog.Term; +import alice.tuprolog.Theory; +import alice.tuprolog.Var; + +public abstract class AbstractPrologCommandPlayer implements CommandPlayer { + + private static final Log log = PlatformUtil.getLog(AbstractPrologCommandPlayer.class); + + protected ClientContext ctx; + protected File voiceDir; + protected Prolog prologSystem; + protected static final String P_VERSION = "version"; + protected static final String P_RESOLVE = "resolve"; + public static final String A_LEFT = "left"; + public static final String A_LEFT_SH = "left_sh"; + public static final String A_LEFT_SL = "left_sl"; + public static final String A_LEFT_KEEP = "left_keep"; + public static final String A_RIGHT = "right"; + public static final String A_RIGHT_SH = "right_sh"; + public static final String A_RIGHT_SL = "right_sl"; + public static final String A_RIGHT_KEEP = "right_keep"; + protected static final String DELAY_CONST = "delay_"; + /** Must be sorted array! */ + private final int[] sortedVoiceVersions; + private AudioFocusHelper mAudioFocusHelper; + + protected int streamType; + + protected AbstractPrologCommandPlayer(ClientContext ctx, String voiceProvider, String configFile, int[] sortedVoiceVersions) + throws CommandPlayerException + { + this.ctx = ctx; + this.sortedVoiceVersions = sortedVoiceVersions; + long time = System.currentTimeMillis(); + try { + this.ctx = ctx; + prologSystem = new Prolog(getLibraries()); + } catch (InvalidLibraryException e) { + log.error("Initializing error", e); //$NON-NLS-1$ + throw new RuntimeException(e); + } + if (log.isInfoEnabled()) { + log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ + } + this.streamType = ctx.getSettings().AUDIO_STREAM_GUIDANCE.get(); + init(voiceProvider, ctx.getSettings(), configFile); + } + + public String[] getLibraries(){ + return new String[] { "alice.tuprolog.lib.BasicLibrary", + "alice.tuprolog.lib.ISOLibrary"}; + } + + private void init(String voiceProvider, OsmandSettings settings, String configFile) throws CommandPlayerException { + prologSystem.clearTheory(); + voiceDir = null; + if (voiceProvider != null) { + File parent = ctx.getAppPath(IndexConstants.VOICE_INDEX_DIR); + voiceDir = new File(parent, voiceProvider); + if (!voiceDir.exists()) { + voiceDir = null; + throw new CommandPlayerException( + ctx.getString(R.string.voice_data_unavailable)); + } + } + + // see comments below why it is impossible to read from zip (don't know + // how to play file from zip) + // voiceZipFile = null; + if (voiceDir != null) { + long time = System.currentTimeMillis(); + boolean wrong = false; + try { + InputStream config; + // if (voiceDir.getName().endsWith(".zip")) { //$NON-NLS-1$ + // voiceZipFile = new ZipFile(voiceDir); + // config = voiceZipFile.getInputStream(voiceZipFile.getEntry("_config.p")); //$NON-NLS-1$ + // } else { + config = new FileInputStream(new File(voiceDir, configFile)); //$NON-NLS-1$ + // } + MetricsConstants mc = settings.METRIC_SYSTEM.get(); + prologSystem.addTheory(new Theory("measure('"+mc.toTTSString()+"').")); + prologSystem.addTheory(new Theory(config)); + } catch (InvalidTheoryException e) { + log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$ + wrong = true; + } catch (IOException e) { + log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$ + wrong = true; + } + if (wrong) { + throw new CommandPlayerException(ctx.getString(R.string.voice_data_corrupted)); + } else { + Term val = solveSimplePredicate(P_VERSION); + if (!(val instanceof Number) || Arrays.binarySearch(sortedVoiceVersions,((Number)val).intValue()) < 0) { + throw new CommandPlayerException(ctx.getString(R.string.voice_data_not_supported)); + } + } + if (log.isInfoEnabled()) { + log.info("Initializing voice subsystem " + voiceProvider + " : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$ + } + + } + } + + protected Term solveSimplePredicate(String predicate) { + Term val = null; + Var v = new Var("MyVariable"); //$NON-NLS-1$ + SolveInfo s = prologSystem.solve(new Struct(predicate, v)); + if (s.isSuccess()) { + prologSystem.solveEnd(); + try { + val = s.getVarValue(v.getName()); + } catch (NoSolutionException e) { + } + } + return val; + } + + @Override + public List execute(List listCmd){ + Struct list = new Struct(listCmd.toArray(new Term[listCmd.size()])); + Var result = new Var("RESULT"); //$NON-NLS-1$ + List files = new ArrayList(); + SolveInfo res = prologSystem.solve(new Struct(P_RESOLVE, list, result)); + + if (res.isSuccess()) { + try { + prologSystem.solveEnd(); + Term solution = res.getVarValue(result.getName()); + + Iterator listIterator = ((Struct) solution).listIterator(); + while(listIterator.hasNext()){ + Object term = listIterator.next(); + if(term instanceof Struct){ + files.add(((Struct) term).getName()); + } + } + + } catch (NoSolutionException e) { + } + } + return files; + } + + @Override + public String getCurrentVoice() { + if (voiceDir == null) { + return null; + } + return voiceDir.getName(); + } + + @Override + public CommandBuilder newCommandBuilder() { + return new CommandBuilder(this); + } + + @Override + public void clear() { + ctx = null; + prologSystem = null; + } + + @Override + public void updateAudioStream(int streamType) { + this.streamType = streamType; + } + + protected void requestAudioFocus() { + log.debug("requestAudioFocus"); + mAudioFocusHelper = ctx.getExternalServiceAPI().getAudioFocuseHelper(); + if (mAudioFocusHelper != null) { + mAudioFocusHelper.requestFocus(ctx, streamType); + } + } + + protected void abandonAudioFocus() { + log.debug("abandonAudioFocus"); + if (mAudioFocusHelper != null) { + mAudioFocusHelper.abandonFocus(ctx, streamType); + mAudioFocusHelper = null; + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/plus/voice/CommandBuilder.java b/OsmAnd-java/src/net/osmand/plus/voice/CommandBuilder.java new file mode 100644 index 0000000000..cd5e7c7f58 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/voice/CommandBuilder.java @@ -0,0 +1,202 @@ +package net.osmand.plus.voice; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import net.osmand.PlatformUtil; + +import org.apache.commons.logging.Log; + +import alice.tuprolog.Struct; +import alice.tuprolog.Term; + +public class CommandBuilder { + + private static final Log log = PlatformUtil.getLog(CommandBuilder.class); + + protected static final String C_PREPARE_TURN = "prepare_turn"; //$NON-NLS-1$ + protected static final String C_PREPARE_ROUNDABOUT = "prepare_roundabout"; //$NON-NLS-1$ + protected static final String C_PREPARE_MAKE_UT = "prepare_make_ut"; //$NON-NLS-1$ + protected static final String C_ROUNDABOUT = "roundabout"; //$NON-NLS-1$ + protected static final String C_GO_AHEAD = "go_ahead"; //$NON-NLS-1$ + protected static final String C_TURN = "turn"; //$NON-NLS-1$ + protected static final String C_MAKE_UT = "make_ut"; //$NON-NLS-1$ + protected static final String C_MAKE_UTWP = "make_ut_wp"; //$NON-NLS-1$ + protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$ + protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$ + protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$ + protected static final String C_AND_ARRIVE_INTERMEDIATE = "and_arrive_intermediate"; //$NON-NLS-1$ + protected static final String C_REACHED_INTERMEDIATE = "reached_intermediate"; //$NON-NLS-1$ + protected static final String C_THEN = "then"; //$NON-NLS-1$ + + protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$ + protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$ + protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$ + protected static final String C_ROUTE_NEW_CALC = "route_new_calc"; //$NON-NLS-1$ + protected static final String C_LOCATION_LOST = "location_lost"; //$NON-NLS-1$ + + /** + * + */ + private final CommandPlayer commandPlayer; + private boolean alreadyExecuted = false; + private List listStruct = new ArrayList(); + + public CommandBuilder(CommandPlayer commandPlayer){ + this(commandPlayer, true); + } + + public CommandBuilder(CommandPlayer commandPlayer, boolean preamble) { + this.commandPlayer = commandPlayer; + if (preamble) { + addCommand(C_PREAMBLE); + } + } + + private void checkState(){ + if(alreadyExecuted){ + throw new IllegalArgumentException(); + } + } + + private CommandBuilder addCommand(String name, Object... args){ + checkState(); + Term[] list = new Term[args.length]; + for (int i = 0; i < args.length; i++) { + Object o = args[i]; + if(o instanceof java.lang.Number){ + if(o instanceof java.lang.Double){ + list[i] = new alice.tuprolog.Double((Double) o); + } else if(o instanceof java.lang.Float){ + list[i] = new alice.tuprolog.Float((Float) o); + } else if(o instanceof java.lang.Long){ + list[i] = new alice.tuprolog.Long((Long) o); + } else { + list[i] = new alice.tuprolog.Int(((java.lang.Number)o).intValue()); + } + } else if(o instanceof String){ + list[i] = new Struct((String) o); + } + if(list[i]== null){ + throw new NullPointerException(name +" " + o); //$NON-NLS-1$ + } + } + Struct struct = new Struct(name, list); + if(log.isDebugEnabled()){ + log.debug("Adding command : " + name + " " + Arrays.toString(args)); //$NON-NLS-1$ //$NON-NLS-2$ + } + listStruct.add(struct); + return this; + } + + + public CommandBuilder goAhead(){ + return addCommand(C_GO_AHEAD); + } + + public CommandBuilder goAhead(double dist){ + return addCommand(C_GO_AHEAD, dist); + } + + public CommandBuilder makeUTwp(){ + return addCommand(C_MAKE_UTWP); + } + + public CommandBuilder makeUT(){ + return addCommand(C_MAKE_UT); + } + + public CommandBuilder makeUT(double dist){ + return addCommand(C_MAKE_UT, dist); + } + + public CommandBuilder prepareMakeUT(double dist){ + return addCommand(C_PREPARE_MAKE_UT, dist); + } + + + public CommandBuilder turn(String param){ + return addCommand(C_TURN, param); + } + + public CommandBuilder turn(String param, double dist){ + return addCommand(C_TURN, param, dist); + } + + /** + * + * @param param A_LEFT, A_RIGHT, ... + * @param dist + * @return + */ + public CommandBuilder prepareTurn(String param, double dist){ + return addCommand(C_PREPARE_TURN, param, dist); + } + + public CommandBuilder prepareRoundAbout(double dist){ + return addCommand(C_PREPARE_ROUNDABOUT, dist); + } + + public CommandBuilder roundAbout(double dist, double angle, int exit){ + return addCommand(C_ROUNDABOUT, dist, angle, exit); + } + + public CommandBuilder roundAbout(double angle, int exit){ + return addCommand(C_ROUNDABOUT, angle, exit); + } + + public CommandBuilder andArriveAtDestination(){ + return addCommand(C_AND_ARRIVE_DESTINATION); + } + + public CommandBuilder arrivedAtDestination(){ + return addCommand(C_REACHED_DESTINATION); + } + + public CommandBuilder arrivedAtIntermediatePoint() { + return addCommand(C_REACHED_INTERMEDIATE); + } + + public CommandBuilder andArriveAtIntermediatePoint(){ + return addCommand(C_AND_ARRIVE_INTERMEDIATE); + } + + public CommandBuilder bearLeft(){ + return addCommand(C_BEAR_LEFT); + } + + public CommandBuilder bearRight(){ + return addCommand(C_BEAR_RIGHT); + } + + public CommandBuilder then(){ + return addCommand(C_THEN); + } + + public CommandBuilder gpsLocationLost() { + return addCommand(C_LOCATION_LOST); + } + + public CommandBuilder newRouteCalculated(double dist){ + return addCommand(C_ROUTE_NEW_CALC, dist); + } + + public CommandBuilder routeRecalculated(double dist){ + return addCommand(C_ROUTE_RECALC, dist); + } + + + + public void play(){ + this.commandPlayer.playCommands(this); + } + + protected List execute(){ + alreadyExecuted = true; + return this.commandPlayer.execute(listStruct); + } + + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/plus/voice/CommandPlayer.java b/OsmAnd-java/src/net/osmand/plus/voice/CommandPlayer.java new file mode 100644 index 0000000000..d4da089a04 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/voice/CommandPlayer.java @@ -0,0 +1,20 @@ +package net.osmand.plus.voice; + +import java.util.List; + +import alice.tuprolog.Struct; + +public interface CommandPlayer { + + public abstract String getCurrentVoice(); + + public abstract CommandBuilder newCommandBuilder(); + + public abstract void playCommands(CommandBuilder builder); + + public abstract void clear(); + + public abstract List execute(List listStruct); + + public abstract void updateAudioStream(int streamType); +} diff --git a/OsmAnd-java/src/net/osmand/plus/voice/CommandPlayerException.java b/OsmAnd-java/src/net/osmand/plus/voice/CommandPlayerException.java new file mode 100644 index 0000000000..d9d14d8787 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/plus/voice/CommandPlayerException.java @@ -0,0 +1,22 @@ +package net.osmand.plus.voice; + + +/** + * Exception on CommandPlayer + * + * @author Pavol Zibrita + */ +public class CommandPlayerException extends Exception { + + private static final long serialVersionUID = 8413902962574061832L; + private final String error; + + public CommandPlayerException(String error) { + this.error = error; + } + + public String getError() { + return error; + } + +} diff --git a/OsmAnd-java/src/net/osmand/render/Depends-template.render.xml b/OsmAnd-java/src/net/osmand/render/Depends-template.render.xml new file mode 100644 index 0000000000..4893864877 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/Depends-template.render.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/render/High-contrast-roads.render.xml b/OsmAnd-java/src/net/osmand/render/High-contrast-roads.render.xml new file mode 100644 index 0000000000..44644c11b4 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/High-contrast-roads.render.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd-java/src/net/osmand/render/RenderingRule.java b/OsmAnd-java/src/net/osmand/render/RenderingRule.java new file mode 100644 index 0000000000..c1d5f171b1 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/RenderingRule.java @@ -0,0 +1,163 @@ +package net.osmand.render; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class RenderingRule { + + private RenderingRuleProperty[] properties; + private int[] intProperties; + private float[] floatProperties; + private List ifElseChildren; + private List ifChildren; + + private final RenderingRulesStorage storage; + + public RenderingRule(Map attributes, RenderingRulesStorage storage){ + this.storage = storage; + process(attributes); + } + + private void process(Map attributes) { + ArrayList props = new ArrayList(attributes.size()); + intProperties = new int[attributes.size()]; + int i = 0; + Iterator> it = attributes.entrySet().iterator(); + while (it.hasNext()) { + Entry e = it.next(); + RenderingRuleProperty property = storage.PROPS.get(e.getKey()); + if (property != null) { + props.add(property); + + if (property.isString()) { + intProperties[i] = storage.getDictionaryValue(e.getValue()); + } else if (property.isFloat()) { + if (floatProperties == null) { + // lazy creates + floatProperties = new float[attributes.size()]; + } + floatProperties[i] = property.parseFloatValue(e.getValue()); + } else { + intProperties[i] = property.parseIntValue(e.getValue()); + } + i++; + } + } + properties = props.toArray(new RenderingRuleProperty[props.size()]); + } + + private int getPropertyIndex(String property){ + for (int i = 0; i < properties.length; i++) { + RenderingRuleProperty prop = properties[i]; + if (prop.getAttrName().equals(property)) { + return i; + } + } + return -1; + } + + public String getStringPropertyValue(String property) { + int i = getPropertyIndex(property); + if(i >= 0){ + return storage.getStringValue(intProperties[i]); + } + + return null; + } + + public float getFloatPropertyValue(String property) { + int i = getPropertyIndex(property); + if(i >= 0){ + return floatProperties[i]; + } + return 0; + } + + public String getColorPropertyValue(String property) { + int i = getPropertyIndex(property); + if(i >= 0){ + return RenderingRuleProperty.colorToString(intProperties[i]); + } + return null; + } + + public int getIntPropertyValue(String property) { + int i = getPropertyIndex(property); + if(i >= 0){ + return intProperties[i]; + } + return -1; + } + + protected int getIntProp(int ind){ + return intProperties[ind]; + } + + protected float getFloatProp(int ind){ + return floatProperties[ind]; + } + + public RenderingRuleProperty[] getProperties() { + return properties; + } + + @SuppressWarnings("unchecked") + public List getIfChildren() { + return ifChildren != null ? ifChildren : Collections.EMPTY_LIST ; + } + + @SuppressWarnings("unchecked") + public List getIfElseChildren() { + return ifElseChildren != null ? ifElseChildren : Collections.EMPTY_LIST ; + } + + public void addIfChildren(RenderingRule rr){ + if(ifChildren == null){ + ifChildren = new ArrayList(); + } + ifChildren.add(rr); + } + + public void addIfElseChildren(RenderingRule rr){ + if(ifElseChildren == null){ + ifElseChildren = new ArrayList(); + } + ifElseChildren.add(rr); + } + + @Override + public String toString() { + StringBuilder bls = new StringBuilder(); + toString("", bls); + return bls.toString(); + } + + public StringBuilder toString(String indent, StringBuilder bls ) { + bls.append("RenderingRule ["); + for(RenderingRuleProperty p : getProperties()){ + bls.append(" " + p.getAttrName() + "= "); + if(p.isString()){ + bls.append("\"" + getStringPropertyValue(p.getAttrName()) + "\""); + } else if(p.isFloat()){ + bls.append(getFloatPropertyValue(p.getAttrName())); + } else if(p.isColor()){ + bls.append(getColorPropertyValue(p.getAttrName())); + } else if(p.isIntParse()){ + bls.append(getIntPropertyValue(p.getAttrName())); + } + } + bls.append("]"); + indent += " "; + for(RenderingRule rc : getIfElseChildren()){ + bls.append("\n"+indent); + rc.toString(indent, bls); + } + + return bls; + } + +} diff --git a/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java b/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java new file mode 100644 index 0000000000..1fee7ab32a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/RenderingRuleProperty.java @@ -0,0 +1,291 @@ +package net.osmand.render; + + +import net.osmand.PlatformUtil; +import net.osmand.binary.BinaryMapDataObject; + +import org.apache.commons.logging.Log; + + +public class RenderingRuleProperty { + private final static Log log = PlatformUtil.getLog(RenderingRuleProperty.class); + + private final static int INT_TYPE = 1; + private final static int FLOAT_TYPE = 2; + private final static int STRING_TYPE = 3; + private final static int COLOR_TYPE = 4; + private final static int BOOLEAN_TYPE = 5; + + public static final int TRUE_VALUE = 1; + public static final int FALSE_VALUE = 0; + + // Fields C++ + protected final int type; + protected final boolean input; + protected final String attrName; + + protected int id = -1; + + // use for custom rendering rule properties + protected String name; + protected String description; + protected String[] possibleValues; + + private RenderingRuleProperty(String attrName, int type, boolean input){ + this.attrName = attrName; + this.type = type; + this.input = input; + } + + public boolean isInputProperty() { + return input; + } + + public boolean isOutputProperty() { + return !input; + } + + public void setId(int id) { + if (this.id != -1) { + throw new IllegalArgumentException(); + } + this.id = id; + } + + public int getId() { + return id; + } + + public String getAttrName() { + return attrName; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + protected void setName(String name) { + this.name = name; + } + + protected void setDescription(String description) { + this.description = description; + } + + protected void setPossibleValues(String[] possibleValues) { + this.possibleValues = possibleValues; + } + + public String[] getPossibleValues() { + if (isBoolean()) { + return new String[] { "true", "false" }; + } + return possibleValues; + } + + public boolean isBoolean() { + return type == BOOLEAN_TYPE; + } + + public boolean isFloat() { + return type == FLOAT_TYPE; + } + + public boolean isInt() { + return type == INT_TYPE; + } + + public boolean isColor() { + return type == COLOR_TYPE; + } + + public boolean isString() { + return type == STRING_TYPE; + } + + public boolean isIntParse(){ + return type == INT_TYPE || type == STRING_TYPE || type == COLOR_TYPE || type == BOOLEAN_TYPE; + } + + public boolean accept(int ruleValue, int renderingProperty, RenderingRuleSearchRequest req){ + if(!isIntParse() || !input){ + return false; + } + return ruleValue == renderingProperty; + } + + public boolean accept(float ruleValue, float renderingProperty, RenderingRuleSearchRequest req){ + if(type != FLOAT_TYPE || !input){ + return false; + } + return ruleValue == renderingProperty; + } + + @Override + public String toString() { + return "#RenderingRuleProperty " + getAttrName(); + } + + + public int parseIntValue(String value){ + if(type == INT_TYPE){ + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + log.error("Rendering parse " + value); + } + return -1; + } else if(type == BOOLEAN_TYPE){ + return Boolean.parseBoolean(value) ? TRUE_VALUE : FALSE_VALUE; + } else if(type == STRING_TYPE){ + // requires dictionary to parse + return -1; + } else if(type == COLOR_TYPE){ + try { + return parseColor(value); + } catch (RuntimeException e) { + log.error("Rendering parse " + e.getMessage()); + } + return -1; + } else { + return -1; + } + } + + public float parseFloatValue(String value){ + if(type == FLOAT_TYPE){ + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + log.error("Rendering parse " + value); + } + return -1; + } else { + return -1; + } + } + + + + public static RenderingRuleProperty createOutputIntProperty(String name){ + return new RenderingRuleProperty(name, INT_TYPE, false); + } + + public static RenderingRuleProperty createOutputBooleanProperty(String name){ + return new RenderingRuleProperty(name, BOOLEAN_TYPE, false); + } + + public static RenderingRuleProperty createInputBooleanProperty(String name){ + return new RenderingRuleProperty(name, BOOLEAN_TYPE, true); + } + + public static RenderingRuleProperty createOutputFloatProperty(String name){ + return new RenderingRuleProperty(name, FLOAT_TYPE, false); + } + + public static RenderingRuleProperty createOutputStringProperty(String name){ + return new RenderingRuleProperty(name, STRING_TYPE, false); + } + + public static RenderingRuleProperty createInputIntProperty(String name){ + return new RenderingRuleProperty(name, INT_TYPE, true); + } + + public static RenderingRuleProperty createInputColorProperty(String name){ + return new RenderingRuleProperty(name, COLOR_TYPE, true); + } + + public static RenderingRuleProperty createOutputColorProperty(String name){ + return new RenderingRuleProperty(name, COLOR_TYPE, false); + } + + public static RenderingRuleProperty createInputStringProperty(String name){ + return new RenderingRuleProperty(name, STRING_TYPE, true); + } + + public static RenderingRuleProperty createInputLessIntProperty(String name){ + return new RenderingRuleProperty(name, INT_TYPE, true) { + @Override + public boolean accept(int ruleValue, int renderingProperty, RenderingRuleSearchRequest req) { + if(!isIntParse() || !input){ + return false; + } + return ruleValue >= renderingProperty; + } + }; + } + + public static RenderingRuleProperty createInputGreaterIntProperty(String name){ + return new RenderingRuleProperty(name, INT_TYPE, true) { + @Override + public boolean accept(int ruleValue, int renderingProperty, RenderingRuleSearchRequest req) { + if(!isIntParse() || !input){ + return false; + } + return ruleValue <= renderingProperty; + } + }; + } + + public static RenderingRuleProperty createAdditionalStringProperty(String name) { + return new RenderingRuleProperty(name, STRING_TYPE, true) { + @Override + public boolean accept(int ruleValue, int renderingProperty, RenderingRuleSearchRequest req) { + BinaryMapDataObject obj = req.getObject(); + if (obj == null) { + return true; + } + String val = req.getStorage().getStringValue(ruleValue); + int i = val.indexOf('='); + if (i != -1) { + String ts = val.substring(0, i); + String vs = val.substring(i + 1); + Integer ruleInd = req.getObject().getMapIndex().getRule(ts, vs); + if (ruleInd != null) { + if (req.getObject().containsAdditionalType(ruleInd)) { + return true; + } + } + } + return false; + } + }; + } + + /** + * Parse the color string, and return the corresponding color-int. + * If the string cannot be parsed, throws an IllegalArgumentException + * exception. Supported formats are: + * #RRGGBB + * #AARRGGBB + * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', + * 'yellow', 'lightgray', 'darkgray' + */ + public static int parseColor(String colorString) { + if (colorString.charAt(0) == '#') { + // Use a long to avoid rollovers on #ffXXXXXX + long color = Long.parseLong(colorString.substring(1), 16); + if (colorString.length() == 7) { + // Set the alpha value + color |= 0x00000000ff000000; + } else if (colorString.length() != 9) { + throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$ + } + return (int)color; + } + throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$ + } + + public static String colorToString(int color) { + if ((0xFF000000 & color) == 0xFF000000) { + return "#" + Integer.toHexString(color & 0x00FFFFFF); //$NON-NLS-1$ + } else { + return "#" + Integer.toHexString(color); //$NON-NLS-1$ + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/render/RenderingRuleSearchRequest.java b/OsmAnd-java/src/net/osmand/render/RenderingRuleSearchRequest.java new file mode 100644 index 0000000000..4124cb2372 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/RenderingRuleSearchRequest.java @@ -0,0 +1,241 @@ +package net.osmand.render; + +import net.osmand.binary.BinaryMapDataObject; + + +public class RenderingRuleSearchRequest { + + private final RenderingRulesStorage storage; + RenderingRuleProperty[] props; + int[] values; + BinaryMapDataObject object; + float[] fvalues; + + int[] savedValues; + float[] savedFvalues; + + boolean searchResult = false; + + + public final RenderingRuleStorageProperties ALL; + + public RenderingRuleSearchRequest(RenderingRulesStorage storage) { + this.storage = storage; + this.ALL = storage.PROPS; + props = storage.PROPS.getPoperties(); + values = new int[props.length]; + for (int i = 0; i < props.length; i++) { + if (!props[i].isColor()) { + values[i] = -1; + } + } + fvalues = new float[props.length]; + setBooleanFilter(storage.PROPS.R_TEST, true); + saveState(); + } + + public void setStringFilter(RenderingRuleProperty p, String filter) { + assert p.isInputProperty(); + values[p.getId()] = storage.getDictionaryValue(filter); + } + + public void setIntFilter(RenderingRuleProperty p, int filter) { + assert p.isInputProperty(); + values[p.getId()] = filter; + } + + public void setBooleanFilter(RenderingRuleProperty p, boolean filter) { + assert p.isInputProperty(); + values[p.getId()] = filter ? RenderingRuleProperty.TRUE_VALUE : RenderingRuleProperty.FALSE_VALUE; + } + + public void saveState() { + savedValues = new int[values.length]; + savedFvalues = new float[fvalues.length]; + System.arraycopy(values, 0, savedValues, 0, values.length); + System.arraycopy(fvalues, 0, savedFvalues, 0, fvalues.length); + } + + public void clearState() { + System.arraycopy(savedValues, 0, values, 0, values.length); + System.arraycopy(savedFvalues, 0, fvalues, 0, fvalues.length); + object = null; + } + + public void clearValue(RenderingRuleProperty p) { + if(p.isIntParse()){ + values[p.getId()] = savedValues[p.getId()]; + } else { + fvalues[p.getId()] = savedFvalues[p.getId()]; + } + } + + public BinaryMapDataObject getObject() { + return object; + } + + public void setInitialTagValueZoom(String tag, String val, int zoom, BinaryMapDataObject obj){ + clearState(); + object = obj; + setIntFilter(ALL.R_MINZOOM, zoom); + setIntFilter(ALL.R_MAXZOOM, zoom); + setStringFilter(ALL.R_TAG, tag); + setStringFilter(ALL.R_VALUE, val); + } + + public void setTagValueZoomLayer(String tag, String val, int zoom, int layer, BinaryMapDataObject obj){ + object = obj; + setIntFilter(ALL.R_MINZOOM, zoom); + setIntFilter(ALL.R_MAXZOOM, zoom); + setIntFilter(ALL.R_LAYER, layer); + setStringFilter(ALL.R_TAG, tag); + setStringFilter(ALL.R_VALUE, val); + } + + public boolean isFound() { + return searchResult; + } + + public boolean searchRenderingAttribute(String attribute) { + searchResult = false; + RenderingRule rule = storage.getRenderingAttributeRule(attribute); + if(rule == null){ + return false; + } + searchResult = visitRule(rule, true); + return searchResult; + } + + + public boolean search(int state) { + return search(state, true); + } + + public boolean search(int state, boolean loadOutput) { + searchResult = false; + int tagKey = values[storage.PROPS.R_TAG.getId()]; + int valueKey = values[storage.PROPS.R_VALUE.getId()]; + boolean result = searchInternal(state, tagKey, valueKey, loadOutput); + if (result) { + searchResult = true; + return true; + } + result = searchInternal(state, tagKey, 0, loadOutput); + if (result) { + searchResult = true; + return true; + } + result = searchInternal(state, 0, 0, loadOutput); + if (result) { + searchResult = true; + return true; + } + + return false; + } + + + private boolean searchInternal(int state, int tagKey, int valueKey, boolean loadOutput) { + values[storage.PROPS.R_TAG.getId()] = tagKey; + values[storage.PROPS.R_VALUE.getId()] = valueKey; + RenderingRule accept = storage.getRule(state, tagKey, valueKey); + if (accept == null) { + return false; + } + boolean match = visitRule(accept, loadOutput); + return match; + } + + private boolean visitRule(RenderingRule rule, boolean loadOutput) { + RenderingRuleProperty[] properties = rule.getProperties(); + for (int i = 0; i < properties.length; i++) { + RenderingRuleProperty rp = properties[i]; + if (rp.isInputProperty()) { + boolean match; + if (rp.isFloat()) { + match = rp.accept(rule.getFloatProp(i), fvalues[rp.getId()], this); + } else { + match = rp.accept(rule.getIntProp(i), values[rp.getId()], this); + } + if (!match) { + return false; + } + } + } + if (!loadOutput) { + return true; + } + // accept it + for (int i = 0; i < properties.length; i++) { + RenderingRuleProperty rp = properties[i]; + if (rp.isOutputProperty()) { + searchResult = true; + if (rp.isFloat()) { + fvalues[rp.getId()] = rule.getFloatProp(i); + } else { + values[rp.getId()] = rule.getIntProp(i); + } + } + } + + for (RenderingRule rr : rule.getIfElseChildren()) { + boolean match = visitRule(rr, loadOutput); + if (match) { + break; + } + } + + for(RenderingRule rr : rule.getIfChildren()){ + visitRule(rr, loadOutput); + } + return true; + + } + + public boolean isSpecified(RenderingRuleProperty property){ + if(property.isFloat()){ + return fvalues[property.getId()] != 0; + } else { + int val = values[property.getId()]; + if(property.isColor()){ + return val != 0; + } else { + return val != -1; + } + } + } + + public RenderingRuleProperty[] getProperties() { + return props; + } + + public String getStringPropertyValue(RenderingRuleProperty property) { + int val = values[property.getId()]; + if(val < 0){ + return null; + } + return storage.getStringValue(val); + } + + public float getFloatPropertyValue(RenderingRuleProperty property) { + return fvalues[property.getId()]; + } + + public String getColorStringPropertyValue(RenderingRuleProperty property) { + return RenderingRuleProperty.colorToString(values[property.getId()]); + } + + public int getIntPropertyValue(RenderingRuleProperty property) { + return values[property.getId()]; + } + + public int getIntPropertyValue(RenderingRuleProperty property, int defValue) { + int val = values[property.getId()]; + return val == -1 ? defValue : val; + } + + /**/ RenderingRulesStorage getStorage() { + return storage; + } + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/render/RenderingRuleStorageProperties.java b/OsmAnd-java/src/net/osmand/render/RenderingRuleStorageProperties.java new file mode 100644 index 0000000000..2a2578e3a6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/RenderingRuleStorageProperties.java @@ -0,0 +1,243 @@ +package net.osmand.render; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class RenderingRuleStorageProperties { + + public static final String A_DEFAULT_COLOR = "defaultColor"; + public static final String A_SHADOW_RENDERING = "shadowRendering"; + public static final String ATTR_INT_VALUE = "attrIntValue"; + public static final String ATTR_BOOL_VALUE = "attrBoolValue"; + public static final String ATTR_COLOR_VALUE = "attrColorValue"; + public static final String ATTR_STRING_VALUE = "attrStringValue"; + public static final String TEST = "test"; + + public static final String TEXT_LENGTH = "textLength"; + public static final String NAME_TAG = "nameTag"; + public static final String TEXT_SHIELD = "textShield"; + public static final String SHADOW_RADIUS = "shadowRadius"; + public static final String SHADOW_COLOR = "shadowColor"; + public static final String SHADER = "shader"; + public static final String CAP_3 = "cap_3"; + public static final String CAP_2 = "cap_2"; + public static final String CAP = "cap"; + public static final String CAP_0 = "cap_0"; + public static final String CAP__1 = "cap__1"; + public static final String PATH_EFFECT_3 = "pathEffect_3"; + public static final String PATH_EFFECT_2 = "pathEffect_2"; + public static final String PATH_EFFECT = "pathEffect"; + public static final String PATH_EFFECT_0 = "pathEffect_0"; + public static final String PATH_EFFECT__1 = "pathEffect__1"; + public static final String STROKE_WIDTH_3 = "strokeWidth_3"; + public static final String STROKE_WIDTH_2 = "strokeWidth_2"; + public static final String STROKE_WIDTH = "strokeWidth"; + public static final String STROKE_WIDTH_0 = "strokeWidth_0"; + public static final String STROKE_WIDTH__1 = "strokeWidth__1"; + public static final String COLOR_3 = "color_3"; + public static final String COLOR = "color"; + public static final String COLOR_2 = "color_2"; + public static final String COLOR_0 = "color_0"; + public static final String COLOR__1 = "color__1"; + public static final String TEXT_BOLD = "textBold"; + public static final String TEXT_ORDER = "textOrder"; + public static final String TEXT_MIN_DISTANCE = "textMinDistance"; + public static final String TEXT_ON_PATH = "textOnPath"; + public static final String ICON = "icon"; + public static final String LAYER = "layer"; + public static final String ORDER = "order"; + public static final String OBJECT_TYPE = "objectType"; + public static final String POINT = "point"; + public static final String AREA = "area"; + public static final String CYCLE = "cycle"; + public static final String TAG = "tag"; + public static final String VALUE = "value"; + public static final String MINZOOM = "minzoom"; + public static final String MAXZOOM = "maxzoom"; + public static final String ADDITIONAL = "additional"; + public static final String NIGHT_MODE = "nightMode"; + public static final String TEXT_DY = "textDy"; + public static final String TEXT_SIZE = "textSize"; + public static final String TEXT_COLOR = "textColor"; + public static final String TEXT_HALO_RADIUS = "textHaloRadius"; + public static final String TEXT_WRAP_WIDTH = "textWrapWidth"; + public static final String SHADOW_LEVEL = "shadowLevel"; + + + public RenderingRuleProperty R_TEST; + public RenderingRuleProperty R_ATTR_INT_VALUE; + public RenderingRuleProperty R_ATTR_BOOL_VALUE; + public RenderingRuleProperty R_ATTR_COLOR_VALUE; + public RenderingRuleProperty R_ATTR_STRING_VALUE; + public RenderingRuleProperty R_TEXT_LENGTH; + public RenderingRuleProperty R_NAME_TAG; + public RenderingRuleProperty R_TEXT_SHIELD; + public RenderingRuleProperty R_SHADOW_RADIUS; + public RenderingRuleProperty R_SHADOW_COLOR; + public RenderingRuleProperty R_SHADER; + public RenderingRuleProperty R_CAP_3; + public RenderingRuleProperty R_CAP_2; + public RenderingRuleProperty R_CAP; + public RenderingRuleProperty R_CAP_0; + public RenderingRuleProperty R_CAP__1; + public RenderingRuleProperty R_PATH_EFFECT_3; + public RenderingRuleProperty R_PATH_EFFECT_2; + public RenderingRuleProperty R_PATH_EFFECT; + public RenderingRuleProperty R_PATH_EFFECT_0; + public RenderingRuleProperty R_PATH_EFFECT__1; + public RenderingRuleProperty R_STROKE_WIDTH_3; + public RenderingRuleProperty R_STROKE_WIDTH_2; + public RenderingRuleProperty R_STROKE_WIDTH; + public RenderingRuleProperty R_STROKE_WIDTH_0; + public RenderingRuleProperty R_STROKE_WIDTH__1; + public RenderingRuleProperty R_COLOR_3; + public RenderingRuleProperty R_COLOR; + public RenderingRuleProperty R_COLOR_2; + public RenderingRuleProperty R_COLOR_0; + public RenderingRuleProperty R_COLOR__1; + public RenderingRuleProperty R_TEXT_BOLD; + public RenderingRuleProperty R_TEXT_ORDER; + public RenderingRuleProperty R_TEXT_MIN_DISTANCE; + public RenderingRuleProperty R_TEXT_ON_PATH; + public RenderingRuleProperty R_ICON; + public RenderingRuleProperty R_LAYER; + public RenderingRuleProperty R_ORDER; + public RenderingRuleProperty R_POINT; + public RenderingRuleProperty R_AREA; + public RenderingRuleProperty R_CYCLE; + public RenderingRuleProperty R_OBJECT_TYPE; + public RenderingRuleProperty R_TAG; + public RenderingRuleProperty R_VALUE; + public RenderingRuleProperty R_MINZOOM; + public RenderingRuleProperty R_ADDITIONAL; + public RenderingRuleProperty R_SHADOW_LEVEL; + public RenderingRuleProperty R_MAXZOOM; + public RenderingRuleProperty R_NIGHT_MODE; + public RenderingRuleProperty R_TEXT_DY; + public RenderingRuleProperty R_TEXT_SIZE; + public RenderingRuleProperty R_TEXT_COLOR; + public RenderingRuleProperty R_TEXT_HALO_RADIUS; + public RenderingRuleProperty R_TEXT_WRAP_WIDTH; + + final Map properties; + // C++ + final List rules ; + final List customRules ; + + public RenderingRuleStorageProperties() { + properties = new LinkedHashMap(); + rules = new ArrayList(); + customRules = new ArrayList(); + createDefaultRenderingRuleProperties(); + } + + public RenderingRuleStorageProperties(RenderingRuleStorageProperties toClone) { + properties = new LinkedHashMap(toClone.properties); + rules = new ArrayList(toClone.rules); + customRules = new ArrayList(toClone.customRules); + createDefaultRenderingRuleProperties(); + } + + public void createDefaultRenderingRuleProperties() { + R_TEST = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(TEST)); + R_TAG = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(TAG)); + R_VALUE = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(VALUE)); + R_ADDITIONAL = registerRuleInternal(RenderingRuleProperty.createAdditionalStringProperty(ADDITIONAL)); + R_MINZOOM = registerRuleInternal(RenderingRuleProperty.createInputGreaterIntProperty(MINZOOM)); + R_MAXZOOM = registerRuleInternal(RenderingRuleProperty.createInputLessIntProperty(MAXZOOM)); + R_NIGHT_MODE = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(NIGHT_MODE)); + R_LAYER = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(LAYER)); + R_POINT = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(POINT)); + R_AREA = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(AREA)); + R_CYCLE = registerRuleInternal(RenderingRuleProperty.createInputBooleanProperty(CYCLE)); + + R_TEXT_LENGTH = registerRuleInternal(RenderingRuleProperty.createInputIntProperty(TEXT_LENGTH)); + R_NAME_TAG = registerRuleInternal(RenderingRuleProperty.createInputStringProperty(NAME_TAG)); + + R_ATTR_INT_VALUE = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(ATTR_INT_VALUE)); + R_ATTR_BOOL_VALUE = registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(ATTR_BOOL_VALUE)); + R_ATTR_COLOR_VALUE = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(ATTR_COLOR_VALUE)); + R_ATTR_STRING_VALUE = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(ATTR_STRING_VALUE)); + + // order - no sense to make it float + R_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(ORDER)); + R_OBJECT_TYPE = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(OBJECT_TYPE)); + R_SHADOW_LEVEL = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(SHADOW_LEVEL)); + + // text properties + R_TEXT_WRAP_WIDTH = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_WRAP_WIDTH)); + R_TEXT_DY = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_DY)); + R_TEXT_HALO_RADIUS = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_HALO_RADIUS)); + R_TEXT_SIZE = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_SIZE)); + R_TEXT_ORDER = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_ORDER)); + R_TEXT_MIN_DISTANCE = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(TEXT_MIN_DISTANCE)); + R_TEXT_SHIELD = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(TEXT_SHIELD)); + + + R_TEXT_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(TEXT_COLOR)); + + R_TEXT_BOLD = registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(TEXT_BOLD)); + R_TEXT_ON_PATH = registerRuleInternal(RenderingRuleProperty.createOutputBooleanProperty(TEXT_ON_PATH)); + + // point + R_ICON = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(ICON)); + + // polygon/way + R_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR)); + R_COLOR_2 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_2)); + R_COLOR_3 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_3)); + R_COLOR_0 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR_0)); + R_COLOR__1 = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(COLOR__1)); + R_STROKE_WIDTH = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH)); + R_STROKE_WIDTH_2 = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_2)); + R_STROKE_WIDTH_3 = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_3)); + R_STROKE_WIDTH_0 = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH_0)); + R_STROKE_WIDTH__1 = registerRuleInternal(RenderingRuleProperty.createOutputFloatProperty(STROKE_WIDTH__1)); + + R_PATH_EFFECT = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT)); + R_PATH_EFFECT_2 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_2)); + R_PATH_EFFECT_3 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_3)); + R_PATH_EFFECT_0 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT_0)); + R_PATH_EFFECT__1 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(PATH_EFFECT__1)); + R_CAP = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP)); + R_CAP_2 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_2)); + R_CAP_3 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_3)); + R_CAP_0 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP_0)); + R_CAP__1 = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(CAP__1)); + R_SHADER = registerRuleInternal(RenderingRuleProperty.createOutputStringProperty(SHADER)); + + R_SHADOW_COLOR = registerRuleInternal(RenderingRuleProperty.createOutputColorProperty(SHADOW_COLOR)); + R_SHADOW_RADIUS = registerRuleInternal(RenderingRuleProperty.createOutputIntProperty(SHADOW_RADIUS)); + } + + public RenderingRuleProperty get(String name) { + return properties.get(name); + } + + public RenderingRuleProperty[] getPoperties() { + return rules.toArray(new RenderingRuleProperty[rules.size()]); + } + + public List getCustomRules() { + return customRules; + } + + private RenderingRuleProperty registerRuleInternal(RenderingRuleProperty p) { + if(get(p.getAttrName()) == null) { + properties.put(p.getAttrName(), p); + p.setId(rules.size()); + rules.add(p); + } + return get(p.getAttrName()); + } + + public RenderingRuleProperty registerRule(RenderingRuleProperty p) { + RenderingRuleProperty ps = registerRuleInternal(p); + if(!customRules.contains(ps)) { + customRules.add(p); + } + return ps; + } +} diff --git a/OsmAnd-java/src/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/net/osmand/render/RenderingRulesStorage.java new file mode 100644 index 0000000000..1f03751f09 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/RenderingRulesStorage.java @@ -0,0 +1,495 @@ +package net.osmand.render; + +import gnu.trove.map.hash.TIntObjectHashMap; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Stack; + +import net.osmand.PlatformUtil; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +public class RenderingRulesStorage { + + private final static Log log = PlatformUtil.getLog(RenderingRulesStorage.class); + + // keep sync ! + // keep sync ! not change values + public final static int MULTY_POLYGON_TYPE = 0; + public final static int POINT_RULES = 1; + public final static int LINE_RULES = 2; + public final static int POLYGON_RULES = 3; + public final static int TEXT_RULES = 4; + public final static int ORDER_RULES = 5; + private final static int LENGTH_RULES = 6; + + private final static int SHIFT_TAG_VAL = 16; + + // C++ + List dictionary = new ArrayList(); + Map dictionaryMap = new LinkedHashMap(); + + public RenderingRuleStorageProperties PROPS = new RenderingRuleStorageProperties(); + + @SuppressWarnings("unchecked") + protected TIntObjectHashMap[] tagValueGlobalRules = new TIntObjectHashMap[LENGTH_RULES]; + + protected Map renderingAttributes = new LinkedHashMap(); + protected Map renderingConstants= new LinkedHashMap(); + + private String renderingName; + private String internalRenderingName; + + + public static interface RenderingRulesStorageResolver { + + RenderingRulesStorage resolve(String name, RenderingRulesStorageResolver ref) throws XmlPullParserException, IOException; + } + + public RenderingRulesStorage(String name, Map renderingConstants){ + getDictionaryValue(""); + this.renderingName = name; + if(renderingConstants != null) { + this.renderingConstants.putAll(renderingConstants); + } + } + + public int getDictionaryValue(String val) { + if(dictionaryMap.containsKey(val)){ + return dictionaryMap.get(val); + } + int nextInd = dictionaryMap.size(); + dictionaryMap.put(val, nextInd); + dictionary.add(val); + return nextInd; + + } + + public String getStringValue(int i){ + return dictionary.get(i); + } + + + public String getName() { + return renderingName; + } + + public String getInternalRenderingName() { + return internalRenderingName; + } + + + public void parseRulesFromXmlInputStream(InputStream is, RenderingRulesStorageResolver resolver) throws XmlPullParserException, + IOException { + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + RenderingRulesHandler handler = new RenderingRulesHandler(parser, resolver); + handler.parse(is); + RenderingRulesStorage depends = handler.getDependsStorage(); + if (depends != null) { + // merge results + // dictionary and props are already merged + Iterator> it = depends.renderingAttributes.entrySet().iterator(); + while (it.hasNext()) { + Entry e = it.next(); + if (renderingAttributes.containsKey(e.getKey())) { + RenderingRule root = renderingAttributes.get(e.getKey()); + List list = e.getValue().getIfElseChildren(); + for (RenderingRule every : list) { + root.addIfElseChildren(every); + } + } else { + renderingAttributes.put(e.getKey(), e.getValue()); + } + } + + for (int i = 0; i < LENGTH_RULES; i++) { + if (depends.tagValueGlobalRules[i] == null || depends.tagValueGlobalRules[i].isEmpty()) { + continue; + } + if (tagValueGlobalRules[i] != null) { + int[] keys = depends.tagValueGlobalRules[i].keys(); + for (int j = 0; j < keys.length; j++) { + RenderingRule rule = tagValueGlobalRules[i].get(keys[j]); + RenderingRule dependsRule = depends.tagValueGlobalRules[i].get(keys[j]); + if (dependsRule != null) { + if (rule != null) { + RenderingRule toInsert = createTagValueRootWrapperRule(keys[j], rule); + toInsert.addIfElseChildren(dependsRule); + tagValueGlobalRules[i].put(keys[j], toInsert); + } else { + tagValueGlobalRules[i].put(keys[j], dependsRule); + } + } + } + } else { + tagValueGlobalRules[i] = depends.tagValueGlobalRules[i]; + } + } + + } + } + + public static String colorToString(int color) { + if ((0xFF000000 & color) == 0xFF000000) { + return "#" + Integer.toHexString(color & 0x00FFFFFF); //$NON-NLS-1$ + } else { + return "#" + Integer.toHexString(color); //$NON-NLS-1$ + } + } + + private void registerGlobalRule(RenderingRule rr, int state, Map attrsMap) throws XmlPullParserException { + int tag = rr.getIntPropertyValue(RenderingRuleStorageProperties.TAG); + if(tag == -1){ + throw new XmlPullParserException("Attribute tag should be specified for root filter " + attrsMap.toString()); + } + int value = rr.getIntPropertyValue(RenderingRuleStorageProperties.VALUE); + if(value == -1){ + throw new XmlPullParserException("Attribute tag should be specified for root filter " + attrsMap.toString()); + } + int key = (tag << SHIFT_TAG_VAL) + value; + RenderingRule toInsert = rr; + RenderingRule previous = tagValueGlobalRules[state].get(key); + if(previous != null){ + // all root rules should have at least tag/value + toInsert = createTagValueRootWrapperRule(key, previous); + toInsert.addIfElseChildren(rr); + } + tagValueGlobalRules[state].put(key, toInsert); + } + + + private RenderingRule createTagValueRootWrapperRule(int tagValueKey, RenderingRule previous) { + if (previous.getProperties().length > 2) { + Map m = new HashMap(); + m.put("tag", getTagString(tagValueKey)); + m.put("value", getValueString(tagValueKey)); + RenderingRule toInsert = new RenderingRule(m, RenderingRulesStorage.this); + toInsert.addIfElseChildren(previous); + return toInsert; + } else { + return previous; + } + } + + private class GroupRules { + Map groupAttributes = new LinkedHashMap(); + List children = new ArrayList(); + List childrenGroups = new ArrayList(); + + private void addGroupFilter(RenderingRule rr) { + for (RenderingRule ch : children) { + ch.addIfChildren(rr); + } + for(GroupRules gch : childrenGroups){ + gch.addGroupFilter(rr); + } + } + + public void registerGlobalRules(int state) throws XmlPullParserException { + for (RenderingRule ch : children) { + registerGlobalRule(ch, state, groupAttributes); + } + for(GroupRules gch : childrenGroups){ + gch.registerGlobalRules(state); + } + + } + } + + private class RenderingRulesHandler { + private final XmlPullParser parser; + private int state; + + Stack stack = new Stack(); + + Map attrsMap = new LinkedHashMap(); + private final RenderingRulesStorageResolver resolver; + private RenderingRulesStorage dependsStorage; + + + + public RenderingRulesHandler(XmlPullParser parser, RenderingRulesStorageResolver resolver){ + this.parser = parser; + this.resolver = resolver; + } + + public void parse(InputStream is) throws XmlPullParserException, IOException { + parser.setInput(is, "UTF-8"); + int tok; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + startElement(parser.getName()); + } else if (tok == XmlPullParser.END_TAG) { + endElement(parser.getName()); + } + } + + } + + public RenderingRulesStorage getDependsStorage() { + return dependsStorage; + } + + public void startElement(String name) throws XmlPullParserException, IOException { + boolean stateChanged = false; + if("filter".equals(name)){ //$NON-NLS-1$ + attrsMap.clear(); + if (stack.size() > 0 && stack.peek() instanceof GroupRules) { + GroupRules parent = ((GroupRules) stack.peek()); + attrsMap.putAll(parent.groupAttributes); + } + parseAttributes(attrsMap); + RenderingRule renderingRule = new RenderingRule(attrsMap, RenderingRulesStorage.this); + + if (stack.size() > 0 && stack.peek() instanceof GroupRules) { + GroupRules parent = ((GroupRules) stack.peek()); + parent.children.add(renderingRule); + } else if (stack.size() > 0 && stack.peek() instanceof RenderingRule) { + RenderingRule parent = ((RenderingRule) stack.peek()); + parent.addIfElseChildren(renderingRule); + } else { + registerGlobalRule(renderingRule, state, attrsMap); + } + stack.push(renderingRule); + } else if("groupFilter".equals(name)){ //$NON-NLS-1$ + attrsMap.clear(); + parseAttributes(attrsMap); + RenderingRule renderingRule = new RenderingRule(attrsMap, RenderingRulesStorage.this); + if (stack.size() > 0 && stack.peek() instanceof GroupRules) { + GroupRules parent = ((GroupRules) stack.peek()); + parent.addGroupFilter(renderingRule); + } else if (stack.size() > 0 && stack.peek() instanceof RenderingRule) { + ((RenderingRule) stack.peek()).addIfChildren(renderingRule); + } else { + throw new XmlPullParserException("Group filter without parent"); + } + stack.push(renderingRule); + } else if("group".equals(name)){ //$NON-NLS-1$ + GroupRules groupRules = new GroupRules(); + if (stack.size() > 0 && stack.peek() instanceof GroupRules) { + GroupRules parent = ((GroupRules) stack.peek()); + groupRules.groupAttributes.putAll(parent.groupAttributes); + parent.childrenGroups.add(groupRules); + } + parseAttributes(groupRules.groupAttributes); + stack.push(groupRules); + } else if("order".equals(name)){ //$NON-NLS-1$ + state = ORDER_RULES; + stateChanged = true; + } else if("text".equals(name)){ //$NON-NLS-1$ + state = TEXT_RULES; + stateChanged = true; + } else if("point".equals(name)){ //$NON-NLS-1$ + state = POINT_RULES; + stateChanged = true; + } else if("line".equals(name)){ //$NON-NLS-1$ + state = LINE_RULES; + stateChanged = true; + } else if("polygon".equals(name)){ //$NON-NLS-1$ + state = POLYGON_RULES; + stateChanged = true; + } else if("renderingAttribute".equals(name)){ //$NON-NLS-1$ + String attr = parser.getAttributeValue("", "name"); + @SuppressWarnings("unchecked") + RenderingRule root = new RenderingRule(new HashMap( ), RenderingRulesStorage.this); + renderingAttributes.put(attr, root); + stack.push(root); + } else if("renderingProperty".equals(name)){ //$NON-NLS-1$ + String attr = parser.getAttributeValue("", "attr"); + RenderingRuleProperty prop; + String type = parser.getAttributeValue("", "type"); + if("boolean".equalsIgnoreCase(type)){ + prop = RenderingRuleProperty.createInputBooleanProperty(attr); + } else if("string".equalsIgnoreCase(type)){ + prop = RenderingRuleProperty.createInputStringProperty(attr); + } else { + prop = RenderingRuleProperty.createInputIntProperty(attr); + } + prop.setDescription(parser.getAttributeValue("", "description")); + prop.setName(parser.getAttributeValue("", "name")); + if(parser.getAttributeValue("", "possibleValues") != null){ + prop.setPossibleValues(parser.getAttributeValue("", "possibleValues").split(",")); + } + PROPS.registerRule(prop); + } else if("renderingConstant".equals(name)){ //$NON-NLS-1$ + if(!renderingConstants.containsKey(parser.getAttributeValue("", "name"))){ + renderingConstants.put(parser.getAttributeValue("", "name"), parser.getAttributeValue("", "value")); + } + } else if("renderingStyle".equals(name)){ //$NON-NLS-1$ + String depends = parser.getAttributeValue("", "depends"); + if(depends != null && depends.length()> 0){ + this.dependsStorage = resolver.resolve(depends, resolver); + } + if(dependsStorage != null){ + // copy dictionary + dictionary = new ArrayList(dependsStorage.dictionary); + dictionaryMap = new LinkedHashMap(dependsStorage.dictionaryMap); + PROPS = new RenderingRuleStorageProperties(dependsStorage.PROPS); + + } + internalRenderingName = parser.getAttributeValue("", "name"); + + } else if("renderer".equals(name)){ //$NON-NLS-1$ + throw new XmlPullParserException("Rendering style is deprecated and no longer supported."); + } else { + log.warn("Unknown tag : " + name); //$NON-NLS-1$ + } + + if(stateChanged){ + tagValueGlobalRules[state] = new TIntObjectHashMap(); + } + + } + + private Map parseAttributes(Map m) { + for(int i=0; i< parser.getAttributeCount(); i++) { + String name = parser.getAttributeName(i); + String vl = parser.getAttributeValue(i); + if(vl != null && vl.startsWith("$")) { + String cv = vl.substring(1); + if(!renderingConstants.containsKey(cv)){ + throw new IllegalStateException("Rendering constant '" + cv + "' was not specified."); + } + vl = renderingConstants.get(cv); + } + m.put(name, vl); + } + return m; + } + + + public void endElement(String name) throws XmlPullParserException { + if ("filter".equals(name)) { //$NON-NLS-1$ + stack.pop(); + } else if("group".equals(name)){ //$NON-NLS-1$ + GroupRules group = (GroupRules) stack.pop(); + if (stack.size() == 0) { + group.registerGlobalRules(state); + } + } else if("groupFilter".equals(name)){ //$NON-NLS-1$ + stack.pop(); + } else if("renderingAttribute".equals(name)){ //$NON-NLS-1$ + stack.pop(); + } + } + + } + + public int getTagValueKey(String tag, String value){ + int itag = getDictionaryValue(tag); + int ivalue = getDictionaryValue(value); + return (itag << SHIFT_TAG_VAL) | ivalue; + } + + public String getValueString(int tagValueKey){ + return getStringValue(tagValueKey & ((1 << SHIFT_TAG_VAL) - 1)); + } + + public String getTagString(int tagValueKey){ + return getStringValue(tagValueKey >> SHIFT_TAG_VAL); + } + + protected RenderingRule getRule(int state, int itag, int ivalue){ + if(tagValueGlobalRules[state] != null){ + return tagValueGlobalRules[state].get((itag << SHIFT_TAG_VAL) | ivalue); + } + return null; + } + + protected RenderingRule getRenderingAttributeRule(String attribute){ + return renderingAttributes.get(attribute); + } + + public String[] getRenderingAttributeNames() { + return renderingAttributes.keySet().toArray(new String[renderingAttributes.size()]); + } + public RenderingRule[] getRenderingAttributeValues() { + return renderingAttributes.values().toArray(new RenderingRule[renderingAttributes.size()]); + } + + public RenderingRule[] getRules(int state){ + if(state >= tagValueGlobalRules.length || tagValueGlobalRules[state] == null) { + return new RenderingRule[0]; + } + return tagValueGlobalRules[state].values(new RenderingRule[tagValueGlobalRules[state].size()]); + } + + + public void printDebug(int state, PrintStream out){ + for(int key : tagValueGlobalRules[state].keys()) { + RenderingRule rr = tagValueGlobalRules[state].get(key); + out.print("\n\n"+getTagString(key) + " : " + getValueString(key)); + printRenderingRule("", rr, out); + } + } + + private static void printRenderingRule(String indent, RenderingRule rr, PrintStream out){ + out.print(rr.toString(indent, new StringBuilder()).toString()); + } + + + public static void main(String[] args) throws XmlPullParserException, IOException { + RenderingRulesStorage storage = new RenderingRulesStorage("test", null); + final RenderingRulesStorageResolver resolver = new RenderingRulesStorageResolver() { + @Override + public RenderingRulesStorage resolve(String name, RenderingRulesStorageResolver ref) throws XmlPullParserException, IOException { + RenderingRulesStorage depends = new RenderingRulesStorage("test", null); + depends.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream(name + ".render.xml"), ref); + return depends; + } + }; + storage.parseRulesFromXmlInputStream(RenderingRulesStorage.class.getResourceAsStream("winter+ski.render.xml"), resolver); +// storage.printDebug(TEXT_RULES, System.out); +// long tm = System.nanoTime(); +// int count = 100000; +// for (int i = 0; i < count; i++) { + RenderingRuleSearchRequest searchRequest = new RenderingRuleSearchRequest(storage); + searchRequest.setStringFilter(storage.PROPS.R_TAG, "landuse"); + searchRequest.setStringFilter(storage.PROPS.R_VALUE, "wood"); + searchRequest.setIntFilter(storage.PROPS.R_LAYER, 1); + searchRequest.setIntFilter(storage.PROPS.R_MINZOOM, 15); + searchRequest.setIntFilter(storage.PROPS.R_MAXZOOM, 15); + // searchRequest.setBooleanFilter(storage.PROPS.R_NIGHT_MODE, true); + // searchRequest.setBooleanFilter(storage.PROPS.get("hmRendered"), true); + + boolean res = searchRequest.search(POLYGON_RULES); + System.out.println("Result " + res); + printResult(searchRequest, System.out); +// } +// System.out.println((System.nanoTime()- tm)/ (1e6f * count) ); + } + + private static void printResult(RenderingRuleSearchRequest searchRequest, PrintStream out) { + if(searchRequest.isFound()){ + out.print(" Found : "); + for (RenderingRuleProperty rp : searchRequest.getProperties()) { + if(rp.isOutputProperty() && searchRequest.isSpecified(rp)){ + out.print(" " + rp.getAttrName() + "= "); + if(rp.isString()){ + out.print("\"" + searchRequest.getStringPropertyValue(rp) + "\""); + } else if(rp.isFloat()){ + out.print(searchRequest.getFloatPropertyValue(rp)); + } else if(rp.isColor()){ + out.print(searchRequest.getColorStringPropertyValue(rp)); + } else if(rp.isIntParse()){ + out.print(searchRequest.getIntPropertyValue(rp)); + } + } + } + } else { + out.println("Not found"); + } + + } +} diff --git a/OsmAnd-java/src/net/osmand/render/Touring-view_(more-contrast-and-details).render.xml b/OsmAnd-java/src/net/osmand/render/Touring-view_(more-contrast-and-details).render.xml new file mode 100644 index 0000000000..75013674fc --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/Touring-view_(more-contrast-and-details).render.xml @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd-java/src/net/osmand/render/Winter-and-ski.render.xml b/OsmAnd-java/src/net/osmand/render/Winter-and-ski.render.xml new file mode 100644 index 0000000000..876fcc3d63 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/Winter-and-ski.render.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/render/default.render.xml b/OsmAnd-java/src/net/osmand/render/default.render.xml new file mode 100644 index 0000000000..a351c26ba7 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/render/default.render.xml @@ -0,0 +1,1583 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/router/BaseRouteResult.java b/OsmAnd-java/src/net/osmand/router/BaseRouteResult.java new file mode 100644 index 0000000000..efcf6cfbe6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/BaseRouteResult.java @@ -0,0 +1,35 @@ +package net.osmand.router; + +import java.util.List; + +import net.osmand.data.DataTileManager; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; + +public class BaseRouteResult { + + private final List baseResult; + private DataTileManager indexedData = new DataTileManager(15); + + public BaseRouteResult(List baseResult) { + this.baseResult = baseResult; + indexData(); + } + + + private void indexData() { + for(RouteSegmentResult r : baseResult){ +// r.getObject().getPoint31XTile(i); + +// indexedData.evaluateTile(latitude, longitude) + } + + } + + + public float getOrthogonalDistance(RouteSegment r){ + float dist = 0; + int x = r.getRoad().getPoint31XTile(r.getSegmentStart()); + int y = r.getRoad().getPoint31YTile(r.getSegmentStart()); + return dist; + } +} diff --git a/OsmAnd-java/src/net/osmand/router/BinaryRoutePlanner.java b/OsmAnd-java/src/net/osmand/router/BinaryRoutePlanner.java new file mode 100644 index 0000000000..4a79d36da9 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/BinaryRoutePlanner.java @@ -0,0 +1,854 @@ +package net.osmand.router; + +import gnu.trove.map.hash.TLongObjectHashMap; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.PriorityQueue; + +import net.osmand.PlatformUtil; +import net.osmand.binary.RouteDataBorderLinePoint; +import net.osmand.binary.RouteDataObject; +import net.osmand.osm.MapRenderingTypes; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +public class BinaryRoutePlanner { + + private final int REVERSE_WAY_RESTRICTION_ONLY = 1024; + /*private*/ final int STANDARD_ROAD_IN_QUEUE_OVERHEAD = 220; + /*private */final int STANDARD_ROAD_VISITED_OVERHEAD = 150; + + protected static final Log log = PlatformUtil.getLog(BinaryRoutePlanner.class); + + private static final int ROUTE_POINTS = 11; + private static final boolean TRACE_ROUTING = false; + + + public static double squareRootDist(int x1, int y1, int x2, int y2) { + // translate into meters + double dy = MapUtils.convert31YToMeters(y1, y2); + double dx = MapUtils.convert31XToMeters(x1, x2); + return Math.sqrt(dx * dx + dy * dy); +// return measuredDist(x1, y1, x2, y2); + } + + + private static class SegmentsComparator implements Comparator { + final RoutingContext ctx; + public SegmentsComparator(RoutingContext ctx) { + this.ctx = ctx; + } + @Override + public int compare(RouteSegment o1, RouteSegment o2) { + return ctx.roadPriorityComparator(o1.distanceFromStart, o1.distanceToEnd, o2.distanceFromStart, o2.distanceToEnd); + } + } + + private static class NonHeuristicSegmentsComparator implements Comparator { + public NonHeuristicSegmentsComparator() { + } + @Override + public int compare(RouteSegment o1, RouteSegment o2) { + return roadPriorityComparator(o1.distanceFromStart, o1.distanceToEnd, o2.distanceFromStart, o2.distanceToEnd, 0.5); + } + } + /** + * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm) + * return list of segments + */ + @SuppressWarnings("unused") + FinalRouteSegment searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end) throws InterruptedException, IOException { + // measure time + ctx.timeToLoad = 0; + ctx.visitedSegments = 0; + ctx.memoryOverhead = 1000; + ctx.timeToCalculate = System.nanoTime(); + if(ctx.config.initialDirection != null) { + // mark here as positive for further check + ctx.firstRoadId = calculateRoutePointId(start.getRoad(), start.getSegmentStart(), true); + double plusDir = start.getRoad().directionRoute(start.getSegmentStart(), true); + double diff = plusDir - ctx.config.initialDirection; + if(Math.abs(MapUtils.alignAngleDifference(diff)) <= Math.PI / 3) { + ctx.firstRoadDirection = 1; + } else if(Math.abs(MapUtils.alignAngleDifference(diff - Math.PI)) <= Math.PI / 3) { + ctx.firstRoadDirection = -1; + } + + } + + // Initializing priority queue to visit way segments + Comparator nonHeuristicSegmentsComparator = new NonHeuristicSegmentsComparator(); + PriorityQueue graphDirectSegments = new PriorityQueue(50, new SegmentsComparator(ctx)); + PriorityQueue graphReverseSegments = new PriorityQueue(50, new SegmentsComparator(ctx)); + + // Set to not visit one segment twice (stores road.id << X + segmentStart) + TLongObjectHashMap visitedDirectSegments = new TLongObjectHashMap(); + TLongObjectHashMap visitedOppositeSegments = new TLongObjectHashMap(); + + RouteSegment recalcEndSegment = smartRecalculationEnabled(ctx, visitedOppositeSegments); + boolean runRecalculation = false; + if(recalcEndSegment != null) { + runRecalculation = true; + end = recalcEndSegment; + } + + // for start : f(start) = g(start) + h(start) = 0 + h(start) = h(start) + float estimatedDistance = (float) estimatedDistance(ctx, ctx.targetX, ctx.targetY, ctx.startX, ctx.startY); + end.distanceToEnd = start.distanceToEnd = estimatedDistance; + + graphDirectSegments.add(start); + graphReverseSegments.add(end); + + // Extract & analyze segment with min(f(x)) from queue while final segment is not found + boolean inverse = false; + boolean init = false; + + PriorityQueue graphSegments; + if(inverse) { + graphSegments = graphReverseSegments; + } else { + graphSegments = graphDirectSegments; + } + ctx.loadBorderPoints(); + + FinalRouteSegment finalSegment = null; + while (!graphSegments.isEmpty()) { + RouteSegment segment = graphSegments.poll(); + // use accumulative approach + ctx.memoryOverhead = (visitedDirectSegments.size() + visitedOppositeSegments.size()) * STANDARD_ROAD_VISITED_OVERHEAD + + (graphDirectSegments.size() + + graphReverseSegments.size()) * STANDARD_ROAD_IN_QUEUE_OVERHEAD; + + if(TRACE_ROUTING){ + printRoad(">", segment); + } + if(segment instanceof FinalRouteSegment) { + if(RoutingContext.SHOW_GC_SIZE){ + log.warn("Estimated overhead " + (ctx.memoryOverhead / (1<<20))+ " mb"); + printMemoryConsumption("Memory occupied after calculation : "); + } + finalSegment = (FinalRouteSegment) segment; + break; + } + if (ctx.memoryOverhead > ctx.config.memoryLimitation * 0.95 && RoutingContext.SHOW_GC_SIZE) { + printMemoryConsumption("Memory occupied before exception : "); + } + if(ctx.memoryOverhead > ctx.config.memoryLimitation * 0.95) { + throw new IllegalStateException("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb"); + } + ctx.visitedSegments++; + if (!inverse) { + processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, + segment, visitedOppositeSegments, true); + processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, + segment, visitedOppositeSegments, false); + } else { + processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, segment, + visitedDirectSegments, true); + processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments,segment, + visitedDirectSegments, false); + } + updateCalculationProgress(ctx, graphDirectSegments, graphReverseSegments); + if(graphReverseSegments.isEmpty()){ + throw new IllegalArgumentException("Route is not found to selected target point."); + } + if(graphDirectSegments.isEmpty()){ + throw new IllegalArgumentException("Route is not found from selected start point."); + } + if(runRecalculation) { + // nothing to do + inverse = false; + } else if (!init) { + inverse = !inverse; + init = true; + } else if (ctx.planRouteIn2Directions()) { + inverse = nonHeuristicSegmentsComparator.compare(graphDirectSegments.peek(), graphReverseSegments.peek()) > 0; + if (graphDirectSegments.size() * 1.3 > graphReverseSegments.size()) { + inverse = true; + } else if (graphDirectSegments.size() < 1.3 * graphReverseSegments.size()) { + inverse = false; + } + } else { + // different strategy : use onedirectional graph + inverse = ctx.getPlanRoadDirection() < 0; + } + if (inverse) { + graphSegments = graphReverseSegments; + } else { + graphSegments = graphDirectSegments; + } + + // check if interrupted + if(ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) { + throw new InterruptedException("Route calculation interrupted"); + } + } + printDebugMemoryInformation(ctx, graphDirectSegments, graphReverseSegments, visitedDirectSegments, visitedOppositeSegments); + return finalSegment; + } + + + private void printMemoryConsumption( String string) { + long h1 = RoutingContext.runGCUsedMemory(); + float mb = (1 << 20); + log.warn(string + h1 / mb); + } + + + private void updateCalculationProgress(final RoutingContext ctx, PriorityQueue graphDirectSegments, + PriorityQueue graphReverseSegments) { + if(ctx.calculationProgress != null) { + ctx.calculationProgress.reverseSegmentQueueSize = graphReverseSegments.size(); + ctx.calculationProgress.directSegmentQueueSize = graphDirectSegments.size(); + if(graphDirectSegments.size() > 0) { + ctx.calculationProgress.distanceFromBegin = + Math.max(graphDirectSegments.peek().distanceFromStart, ctx.calculationProgress.distanceFromBegin); + } + if(graphDirectSegments.size() > 0) { + ctx.calculationProgress.distanceFromEnd = + Math.max(graphReverseSegments.peek().distanceFromStart, ctx.calculationProgress.distanceFromBegin); + } + } + } + + + private RouteSegment smartRecalculationEnabled(final RoutingContext ctx, TLongObjectHashMap visitedOppositeSegments) { + boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0 + && ctx.config.recalculateDistance != 0; + if (runRecalculation) { + RouteSegment previous = null; + List rlist = new ArrayList(); + float distanceThreshold = ctx.config.recalculateDistance; + float threshold = 0; + for(RouteSegmentResult rr : ctx.previouslyCalculatedRoute) { + threshold += rr.getDistance(); + if(threshold > distanceThreshold) { + rlist.add(rr); + } + } + runRecalculation = rlist.size() > 0; + if (rlist.size() > 0) { + for (RouteSegmentResult rr : rlist) { + RouteSegment segment = new RouteSegment(rr.getObject(), rr.getEndPointIndex()); + if (previous != null) { + previous.setParentRoute(segment); + previous.setParentSegmentEnd(rr.getStartPointIndex()); + boolean positive = rr.getStartPointIndex() < rr.getEndPointIndex(); + long t = calculateRoutePointId(rr.getObject(), positive ? rr.getEndPointIndex() - 1 : rr.getEndPointIndex(), + positive); + visitedOppositeSegments.put(t, segment); + } + previous = segment; + } + return previous; + } + } + return null; + } + + + + private void printRoad(String prefix, RouteSegment segment) { + String pr; + if(segment.parentRoute != null){ + pr = " pend="+segment.parentSegmentEnd +" parent=" + segment.parentRoute.road; + } else { + pr = ""; + } + println(prefix +"" + segment.road + " ind=" + segment.getSegmentStart() + + " ds=" + ((float)segment.distanceFromStart) + " es="+((float)segment.distanceToEnd) + pr); + } + + private float estimatedDistance(final RoutingContext ctx, int targetEndX, int targetEndY, + int startX, int startY) { + double distance = squareRootDist(startX, startY, targetEndX, targetEndY); + return (float) (distance / ctx.getRouter().getMaxDefaultSpeed()); + } + + protected static float h(RoutingContext ctx, int begX, int begY, int endX, int endY, + RouteSegment next) { + double distToFinalPoint = squareRootDist(begX, begY, endX, endY); + if (RoutingContext.USE_BORDER_LINES) { + int begBorder = ctx.searchBorderLineIndex(begY); + int endBorder = ctx.searchBorderLineIndex(endY); + if (begBorder != endBorder) { + double res = 0; + boolean plus = begBorder < endBorder; + boolean beginEqStart = begX == ctx.startX && begY == ctx.startY; + boolean beginEqTarget = begX == ctx.targetX && begY == ctx.targetY; + boolean endEqStart = endX == ctx.startX && endY == ctx.startY; + boolean endEqTarget = endX == ctx.targetX && endY == ctx.targetY; + if(endEqStart || endEqTarget) { + // we start from intermediate point and end in target or start + if (begX > ctx.leftBorderBoundary && begX < ctx.rightBorderBoundary) { + List pnts = ctx.borderLines[plus ? begBorder : begBorder - 1].borderPoints; + for (RouteDataBorderLinePoint p : pnts) { + double f = (endEqTarget ? p.distanceToEndPoint : p.distanceToStartPoint) + squareRootDist(p.x, p.y, begX, begY); + if (res > f || res <= 0) { + res = f; + } + } + } + } else if(beginEqStart || beginEqTarget) { + if (endX > ctx.leftBorderBoundary && endX < ctx.rightBorderBoundary) { + List pnts = ctx.borderLines[plus ? endBorder - 1 : endBorder].borderPoints; + for (RouteDataBorderLinePoint p : pnts) { + double f = (beginEqTarget ? p.distanceToEndPoint : p.distanceToStartPoint) + + squareRootDist(p.x, p.y, endX, endY); + if (res > f || res <= 0) { + res = f; + } + } + } + } else { + throw new IllegalStateException(); + } + if(res > 0) { + if(res < distToFinalPoint - 0.01) { + throw new IllegalStateException("Estimated distance " + res + " > " + distToFinalPoint); + } +// if(endEqStart && res - distToFinalPoint > 13000) { +// System.out.println(" Res="+res + " dist=" +distToFinalPoint); +// } + distToFinalPoint = res; + + } else { + // FIXME put penalty +// distToFinalPoint = distToFinalPoint; + } + } + } + + double result = distToFinalPoint / ctx.getRouter().getMaxDefaultSpeed(); + return (float) result; + } + + + + private static void println(String logMsg) { +// log.info(logMsg); + System.out.println(logMsg); + } + + private static void printInfo(String logMsg) { + log.warn(logMsg); + } + + public void printDebugMemoryInformation(RoutingContext ctx, PriorityQueue graphDirectSegments, PriorityQueue graphReverseSegments, + TLongObjectHashMap visitedDirectSegments,TLongObjectHashMap visitedOppositeSegments) { + printInfo("Time to calculate : " + (System.nanoTime() - ctx.timeToCalculate) / 1e6 + ", time to load : " + ctx.timeToLoad / 1e6 + ", time to load headers : " + ctx.timeToLoadHeaders / 1e6); + int maxLoadedTiles = Math.max(ctx.maxLoadedTiles, ctx.getCurrentlyLoadedTiles()); + printInfo("Current loaded tiles : " + ctx.getCurrentlyLoadedTiles() + ", maximum loaded tiles " + maxLoadedTiles); + printInfo("Loaded tiles " + ctx.loadedTiles + " (distinct "+ctx.distinctLoadedTiles+ "), unloaded tiles " + ctx.unloadedTiles + + ", loaded more than once same tiles " + + ctx.loadedPrevUnloadedTiles ); + printInfo("Visited roads " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments); + if (graphDirectSegments != null && graphReverseSegments != null) { + printInfo("Priority queues sizes : " + graphDirectSegments.size() + "/" + graphReverseSegments.size()); + } + if (visitedDirectSegments != null && visitedOppositeSegments != null) { + printInfo("Visited interval sizes: " + visitedDirectSegments.size() + "/" + visitedOppositeSegments.size()); + } + + for(int k=0; k> 17) + " points " + ctx.borderLines[k].borderPoints.size()); + } + + } + + + private void processRouteSegment(final RoutingContext ctx, boolean reverseWaySearch, + PriorityQueue graphSegments, TLongObjectHashMap visitedSegments, + RouteSegment segment, TLongObjectHashMap oppositeSegments, boolean direction) throws IOException { + final RouteDataObject road = segment.road; + boolean initDirectionAllowed = checkIfInitialMovementAllowedOnSegment(ctx, reverseWaySearch, visitedSegments, segment, direction, road); + boolean directionAllowed = initDirectionAllowed; + // Go through all point of the way and find ways to continue + // ! Actually there is small bug when there is restriction to move forward on the way (it doesn't take into account) + float obstaclesTime = 0; + if(segment.getParentRoute() != null && directionAllowed) { + obstaclesTime = (float) ctx.getRouter().calculateTurnTime(segment, direction? segment.getRoad().getPointsLength() - 1 : 0, + segment.getParentRoute(), segment.getParentSegmentEnd()); + } + if(ctx.firstRoadId == calculateRoutePointId(road, segment.getSegmentStart(), true) ) { + if(direction && ctx.firstRoadDirection < 0) { + obstaclesTime += 500; + } else if(!direction && ctx.firstRoadDirection > 0) { + obstaclesTime += 500; + } + } + float segmentDist = 0; + // +/- diff from middle point + int segmentEnd = segment.getSegmentStart(); + while (directionAllowed) { + int prevInd = segmentEnd; + if(direction) { + segmentEnd ++; + } else { + segmentEnd --; + } + if (segmentEnd < 0 || segmentEnd >= road.getPointsLength()) { + directionAllowed = false; + continue; + } + final int intervalId = direction ? segmentEnd - 1 : segmentEnd; + visitedSegments.put(calculateRoutePointId(road, intervalId, direction), segment); + final int x = road.getPoint31XTile(segmentEnd); + final int y = road.getPoint31YTile(segmentEnd); + final int prevx = road.getPoint31XTile(prevInd); + final int prevy = road.getPoint31YTile(prevInd); + if(x == prevx && y == prevy) { + continue; + } + if(RoutingContext.USE_BORDER_LINES) { + int st = ctx.searchBorderLineIndex(y); + int tt = ctx.searchBorderLineIndex(prevy); + if(st != tt){ +// System.out.print(" " + st + " != " + tt + " " + road.id + " ? "); + for(int i = Math.min(st, tt); i < Math.max(st, tt) & i < ctx.borderLines.length ; i++) { + Iterator pnts = ctx.borderLines[i].borderPoints.iterator(); + boolean changed = false; + while(pnts.hasNext()) { + RouteDataBorderLinePoint o = pnts.next(); + if(o.id == road.id) { +// System.out.println("Point removed !"); + pnts.remove(); + changed = true; + } + } + if(changed){ + ctx.updateDistanceForBorderPoints(ctx.startX, ctx.startY, true); + ctx.updateDistanceForBorderPoints(ctx.targetX, ctx.targetY, false); + } + } + } + } + // 2. calculate point and try to load neighbor ways if they are not loaded + segmentDist += squareRootDist(x, y, prevx, prevy); + + // 2.1 calculate possible obstacle plus time + double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentEnd); + if (obstacle < 0) { + directionAllowed = false; + continue; + } + obstaclesTime += obstacle; + + boolean alreadyVisited = checkIfOppositieSegmentWasVisited(ctx, reverseWaySearch, graphSegments, segment, oppositeSegments, road, + segmentEnd, direction, intervalId, segmentDist, obstaclesTime); + if (alreadyVisited) { + directionAllowed = false; + continue; + } + + // could be expensive calculation + // 3. get intersected ways + final RouteSegment roadNext = ctx.loadRouteSegment(x, y, ctx.config.memoryLimitation - ctx.memoryOverhead); + if(roadNext != null && + !((roadNext == segment || roadNext.road.id == road.id) && roadNext.next == null)) { + // check if there are outgoing connections in that case we need to stop processing + boolean outgoingConnections = false; + RouteSegment r = roadNext; + while(r != null && !outgoingConnections) { + if(r.road.id != road.id || r.getSegmentStart() != 0 || r.road.getOneway() != 1){ + outgoingConnections = true; + } + r = r.next; + } + if (outgoingConnections) { + directionAllowed = false; + } + + float distStartObstacles = segment.distanceFromStart + calculateTimeWithObstacles(ctx, road, segmentDist , obstaclesTime); + processIntersections(ctx, graphSegments, visitedSegments, + distStartObstacles, segment, segmentEnd, + roadNext, reverseWaySearch, outgoingConnections); + } + } + if(initDirectionAllowed && ctx.visitor != null){ + ctx.visitor.visitSegment(segment, segmentEnd, true); + } + } + + private boolean checkIfInitialMovementAllowedOnSegment(final RoutingContext ctx, boolean reverseWaySearch, + TLongObjectHashMap visitedSegments, RouteSegment segment, boolean direction, final RouteDataObject road + ) { + boolean directionAllowed; + final int middle = segment.getSegmentStart(); + int oneway = ctx.getRouter().isOneWay(road); + // use positive direction as agreed + if (!reverseWaySearch) { + if(direction){ + directionAllowed = oneway >= 0; + } else { + directionAllowed = oneway <= 0; + } + } else { + if(direction){ + directionAllowed = oneway <= 0; + } else { + directionAllowed = oneway >= 0; + } + } + if(direction) { + if(middle == road.getPointsLength() - 1 || + visitedSegments.containsKey(calculateRoutePointId(road, middle, true)) || + segment.getAllowedDirection() == -1) { + directionAllowed = false; + } + } else { + if(middle == 0 || visitedSegments.containsKey(calculateRoutePointId(road, middle - 1, false)) || + segment.getAllowedDirection() == 1) { + directionAllowed = false; + } + } + return directionAllowed; + } + + private boolean checkIfOppositieSegmentWasVisited(final RoutingContext ctx, boolean reverseWaySearch, + PriorityQueue graphSegments, RouteSegment segment, TLongObjectHashMap oppositeSegments, + final RouteDataObject road, int segmentEnd, boolean positive, int intervalId, float segmentDist, float obstaclesTime) { + long opp = calculateRoutePointId(road, intervalId, !positive); + if (oppositeSegments.containsKey(opp)) { + RouteSegment opposite = oppositeSegments.get(opp); + if (opposite.getSegmentStart() == segmentEnd) { + FinalRouteSegment frs = new FinalRouteSegment(road, segment.getSegmentStart()); + float distStartObstacles = segment.distanceFromStart + calculateTimeWithObstacles(ctx, road, segmentDist , obstaclesTime); + frs.setParentRoute(segment.getParentRoute()); + frs.setParentSegmentEnd(segment.getParentSegmentEnd()); + frs.reverseWaySearch = reverseWaySearch; + frs.distanceFromStart = opposite.distanceFromStart + distStartObstacles; + frs.distanceToEnd = 0; + frs.opposite = opposite; + graphSegments.add(frs); + return true; + } + } + return false; + } + + + private float calculateTimeWithObstacles(RoutingContext ctx, RouteDataObject road, float distOnRoadToPass, float obstaclesTime) { + float priority = ctx.getRouter().defineSpeedPriority(road); + float speed = (ctx.getRouter().defineSpeed(road) * priority); + if (speed == 0) { + speed = (ctx.getRouter().getMinDefaultSpeed() * priority); + } + // speed can not exceed max default speed according to A* + if(speed > ctx.getRouter().getMaxDefaultSpeed()) { + speed = ctx.getRouter().getMaxDefaultSpeed(); + } + float distStartObstacles = obstaclesTime + + distOnRoadToPass / speed; + return distStartObstacles; + + } + + private long calculateRoutePointId(final RouteDataObject road, int intervalId, boolean positive) { + return (road.getId() << ROUTE_POINTS) + (intervalId << 1) + (positive ? 1 : 0); + } + + + private boolean proccessRestrictions(RoutingContext ctx, RouteDataObject road, RouteSegment inputNext, boolean reverseWay) { + ctx.segmentsToVisitPrescripted.clear(); + ctx.segmentsToVisitNotForbidden.clear(); + boolean exclusiveRestriction = false; + RouteSegment next = inputNext; + if (!reverseWay && road.getRestrictionLength() == 0) { + return false; + } + if(!ctx.getRouter().restrictionsAware()) { + return false; + } + while (next != null) { + int type = -1; + if (!reverseWay) { + for (int i = 0; i < road.getRestrictionLength(); i++) { + if (road.getRestrictionId(i) == next.road.id) { + type = road.getRestrictionType(i); + break; + } + } + } else { + for (int i = 0; i < next.road.getRestrictionLength(); i++) { + int rt = next.road.getRestrictionType(i); + long restrictedTo = next.road.getRestrictionId(i); + if (restrictedTo == road.id) { + type = rt; + break; + } + + // Check if there is restriction only to the other than current road + if (rt == MapRenderingTypes.RESTRICTION_ONLY_RIGHT_TURN || rt == MapRenderingTypes.RESTRICTION_ONLY_LEFT_TURN + || rt == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) { + // check if that restriction applies to considered junk + RouteSegment foundNext = inputNext; + while (foundNext != null) { + if (foundNext.getRoad().id == restrictedTo) { + break; + } + foundNext = foundNext.next; + } + if (foundNext != null) { + type = REVERSE_WAY_RESTRICTION_ONLY; // special constant + } + } + } + } + if (type == REVERSE_WAY_RESTRICTION_ONLY) { + // next = next.next; continue; + } else if (type == -1 && exclusiveRestriction) { + // next = next.next; continue; + } else if (type == MapRenderingTypes.RESTRICTION_NO_LEFT_TURN || type == MapRenderingTypes.RESTRICTION_NO_RIGHT_TURN + || type == MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON || type == MapRenderingTypes.RESTRICTION_NO_U_TURN) { + // next = next.next; continue; + } else if (type == -1) { + // case no restriction + ctx.segmentsToVisitNotForbidden.add(next); + } else { + // case exclusive restriction (only_right, only_straight, ...) + // 1. in case we are going backward we should not consider only_restriction + // as exclusive because we have many "in" roads and one "out" + // 2. in case we are going forward we have one "in" and many "out" + if (!reverseWay) { + exclusiveRestriction = true; + ctx.segmentsToVisitNotForbidden.clear(); + ctx.segmentsToVisitPrescripted.add(next); + } else { + ctx.segmentsToVisitNotForbidden.add(next); + } + } + next = next.next; + } + ctx.segmentsToVisitPrescripted.addAll(ctx.segmentsToVisitNotForbidden); + return true; + } + + + + + private void processIntersections(RoutingContext ctx, PriorityQueue graphSegments, + TLongObjectHashMap visitedSegments, float distFromStart, + RouteSegment segment, int segmentEnd, + RouteSegment inputNext, boolean reverseWaySearch, + boolean addSameRoadFutureDirection) { + byte searchDirection = reverseWaySearch ? (byte)-1 : (byte)1; + boolean thereAreRestrictions = proccessRestrictions(ctx, segment.road, inputNext, reverseWaySearch); + Iterator nextIterator = null; + if (thereAreRestrictions) { + nextIterator = ctx.segmentsToVisitPrescripted.iterator(); + if(TRACE_ROUTING){ + println(" >> There are restrictions"); + } + } + // Calculate possible ways to put into priority queue + RouteSegment next = inputNext; + boolean hasNext = nextIterator == null || nextIterator.hasNext(); + while (hasNext) { + if (nextIterator != null) { + next = nextIterator.next(); + } + boolean nextPlusNotAllowed = (next.getSegmentStart() == next.road.getPointsLength() - 1) || + visitedSegments.containsKey(calculateRoutePointId(next.road, next.getSegmentStart(), true)); + boolean nextMinusNotAllowed = (next.getSegmentStart() == 0) || + visitedSegments.containsKey(calculateRoutePointId(next.road, next.getSegmentStart() - 1, false)); + boolean sameRoadFutureDirection = next.road.id == segment.road.id && next.getSegmentStart() == segmentEnd; + // road.id could be equal on roundabout, but we should accept them + boolean alreadyVisited = nextPlusNotAllowed && nextMinusNotAllowed; + boolean skipRoad = sameRoadFutureDirection && !addSameRoadFutureDirection; + if (!alreadyVisited && !skipRoad) { + int targetEndX = reverseWaySearch? ctx.startX : ctx.targetX; + int targetEndY = reverseWaySearch? ctx.startY : ctx.targetY; + float distanceToEnd = h(ctx, segment.getRoad().getPoint31XTile(segmentEnd), + segment.getRoad().getPoint31YTile(segmentEnd), targetEndX, targetEndY, next); + // assigned to wrong direction + if(next.getDirectionAssigned() == -searchDirection){ + next = new RouteSegment(next.getRoad(), next.getSegmentStart()); + } + + if (next.getParentRoute() == null + || ctx.roadPriorityComparator(next.distanceFromStart, next.distanceToEnd, distFromStart, distanceToEnd) > 0) { + if (next.getParentRoute() != null) { + if (!graphSegments.remove(next)) { + throw new IllegalStateException("Should be handled by direction flag"); + } + } + next.assignDirection(searchDirection); + next.distanceFromStart = distFromStart; + next.distanceToEnd = distanceToEnd; + if(sameRoadFutureDirection) { + next.setAllowedDirection((byte) (segment.getSegmentStart() < next.getSegmentStart() ? 1 : - 1)); + } + if(TRACE_ROUTING) { + printRoad(" >>", next); + } + // put additional information to recover whole route after + next.setParentRoute(segment); + next.setParentSegmentEnd(segmentEnd); + + graphSegments.add(next); + } + if (ctx.visitor != null) { +// ctx.visitor.visitSegment(next, false); + } + } else if(!sameRoadFutureDirection){ + // the segment was already visited! We need to follow better route if it exists + // that is very strange situation and almost exception (it can happen when we underestimate distnceToEnd) + if (next.getDirectionAssigned() == searchDirection && + distFromStart < next.distanceFromStart && next.road.id != segment.road.id) { + if(ctx.config.heuristicCoefficient <= 1) { + throw new IllegalStateException("distance from start " + distFromStart + " < " +next.distanceFromStart); + } + // That code is incorrect (when segment is processed itself, + // then it tries to make wrong u-turn) - + // this situation should be very carefully checked in future (seems to be fixed) + next.distanceFromStart = distFromStart; + next.setParentRoute(segment); + next.setParentSegmentEnd(segmentEnd); + if (ctx.visitor != null) { +// ctx.visitor.visitSegment(next, false); + } + } + } + + // iterate to next road + if (nextIterator == null) { + next = next.next; + hasNext = next != null; + } else { + hasNext = nextIterator.hasNext(); + } + } + } + + + /*public */static int roadPriorityComparator(double o1DistanceFromStart, double o1DistanceToEnd, + double o2DistanceFromStart, double o2DistanceToEnd, double heuristicCoefficient ) { + // f(x) = g(x) + h(x) --- g(x) - distanceFromStart, h(x) - distanceToEnd (not exact) + return Double.compare(o1DistanceFromStart + heuristicCoefficient * o1DistanceToEnd, + o2DistanceFromStart + heuristicCoefficient * o2DistanceToEnd); + } + + + public interface RouteSegmentVisitor { + + public void visitSegment(RouteSegment segment, int segmentEnd, boolean poll); + } + + public static class RouteSegment { + final short segStart; + final RouteDataObject road; + // needed to store intersection of routes + RouteSegment next = null; + + // search context (needed for searching route) + // Initially it should be null (!) because it checks was it segment visited before + RouteSegment parentRoute = null; + short parentSegmentEnd = 0; + // 1 - positive , -1 - negative, 0 not assigned + byte directionAssgn = 0; + // 1 - only positive allowed, -1 - only negative allowed + byte allowedDirection = 0; + + // distance measured in time (seconds) + float distanceFromStart = 0; + float distanceToEnd = 0; + + public RouteSegment(RouteDataObject road, int segmentStart) { + this.road = road; + this.segStart = (short) segmentStart; + } + + public byte getDirectionAssigned(){ + return directionAssgn; + } + + public RouteSegment getParentRoute() { + return parentRoute; + } + + public void setParentRoute(RouteSegment parentRoute) { + this.parentRoute = parentRoute; + } + + public void assignDirection(byte b) { + directionAssgn = b; + } + + public byte getAllowedDirection() { + return allowedDirection; + } + + public void setAllowedDirection(byte allowedDirection) { + this.allowedDirection = allowedDirection; + } + + + public void setParentSegmentEnd(int parentSegmentEnd) { + this.parentSegmentEnd = (short) parentSegmentEnd; + } + + public int getParentSegmentEnd() { + return parentSegmentEnd; + } + + public RouteSegment getNext() { + return next; + } + + public int getSegmentStart() { + return segStart; + } + + public RouteDataObject getRoad() { + return road; + } + + public String getTestName(){ + return MessageFormat.format("s{0,number,#.##} e{1,number,#.##}", ((float)distanceFromStart), ((float)distanceToEnd)); + } + + + public Iterator getIterator() { + return new Iterator() { + RouteSegment next = RouteSegment.this; + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public RouteSegment next() { + RouteSegment c = next; + if(next != null) { + next = next.next; + } + return c; + } + + @Override + public boolean hasNext() { + return next != null; + } + }; + } + } + + static class FinalRouteSegment extends RouteSegment { + + boolean reverseWaySearch; + RouteSegment opposite; + + public FinalRouteSegment(RouteDataObject road, int segmentStart) { + super(road, segmentStart); + } + + } + +} diff --git a/OsmAnd-java/src/net/osmand/router/BinaryRoutePlannerOld.java b/OsmAnd-java/src/net/osmand/router/BinaryRoutePlannerOld.java new file mode 100644 index 0000000000..bdd65b420d --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/BinaryRoutePlannerOld.java @@ -0,0 +1,585 @@ +package net.osmand.router; + +import gnu.trove.map.hash.TLongObjectHashMap; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.PriorityQueue; + +import net.osmand.PlatformUtil; +import net.osmand.binary.RouteDataObject; +import net.osmand.osm.MapRenderingTypes; +import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +public class BinaryRoutePlannerOld { + + public static boolean PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true; + private final int REVERSE_WAY_RESTRICTION_ONLY = 1024; + private final int STANDARD_ROAD_IN_QUEUE_OVERHEAD = 900; + + protected static final Log log = PlatformUtil.getLog(BinaryRoutePlannerOld.class); + + private static final int ROUTE_POINTS = 11; + + + private static double squareRootDist(int x1, int y1, int x2, int y2) { + // translate into meters + double dy = MapUtils.convert31YToMeters(y1, y2); + double dx = MapUtils.convert31XToMeters(x1, x2); + return Math.sqrt(dx * dx + dy * dy); +// return measuredDist(x1, y1, x2, y2); + } + + + /** + * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm) + * return list of segments + */ + void searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end) throws IOException, InterruptedException { + // measure time + ctx.timeToLoad = 0; + ctx.visitedSegments = 0; + ctx.timeToCalculate = System.nanoTime(); + if(ctx.config.initialDirection != null) { + ctx.firstRoadId = (start.getRoad().id << ROUTE_POINTS) + start.getSegmentStart(); + double plusDir = start.getRoad().directionRoute(start.getSegmentStart(), true); + double diff = plusDir - ctx.config.initialDirection; + if(Math.abs(MapUtils.alignAngleDifference(diff)) <= Math.PI / 3) { + ctx.firstRoadDirection = 1; + } else if(Math.abs(MapUtils.alignAngleDifference(diff - Math.PI)) <= Math.PI / 3) { + ctx.firstRoadDirection = -1; + } + + } + + // Initializing priority queue to visit way segments + Comparator segmentsComparator = new Comparator(){ + @Override + public int compare(RouteSegment o1, RouteSegment o2) { + return ctx.roadPriorityComparator(o1.distanceFromStart, o1.distanceToEnd, o2.distanceFromStart, o2.distanceToEnd); + } + }; + + Comparator nonHeuristicSegmentsComparator = new Comparator(){ + @Override + public int compare(RouteSegment o1, RouteSegment o2) { + return roadPriorityComparator(o1.distanceFromStart, o1.distanceToEnd, o2.distanceFromStart, o2.distanceToEnd, 0.5); + } + }; + + PriorityQueue graphDirectSegments = new PriorityQueue(50, segmentsComparator); + PriorityQueue graphReverseSegments = new PriorityQueue(50, segmentsComparator); + + // Set to not visit one segment twice (stores road.id << X + segmentStart) + TLongObjectHashMap visitedDirectSegments = new TLongObjectHashMap(); + TLongObjectHashMap visitedOppositeSegments = new TLongObjectHashMap(); + + boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0 + && ctx.config.recalculateDistance != 0; + if (runRecalculation) { + RouteSegment previous = null; + List rlist = new ArrayList(); + float distanceThreshold = ctx.config.recalculateDistance; + float threshold = 0; + for(RouteSegmentResult rr : ctx.previouslyCalculatedRoute) { + threshold += rr.getDistance(); + if(threshold > distanceThreshold) { + rlist.add(rr); + } + } + runRecalculation = rlist.size() > 0; + if (rlist.size() > 0) { + for (RouteSegmentResult rr : rlist) { + RouteSegment segment = new RouteSegment(rr.getObject(), rr.getEndPointIndex()); + if (previous != null) { + previous.setParentRoute(segment); + previous.setParentSegmentEnd(rr.getStartPointIndex()); + long t = (rr.getObject().getId() << ROUTE_POINTS) + segment.getSegmentStart(); + visitedOppositeSegments.put(t, segment); + } + previous = segment; + } + end = previous; + } + } + + // for start : f(start) = g(start) + h(start) = 0 + h(start) = h(start) + int targetEndX = end.road.getPoint31XTile(end.getSegmentStart()); + int targetEndY = end.road.getPoint31YTile(end.getSegmentStart()); + int startX = start.road.getPoint31XTile(start.getSegmentStart()); + int startY = start.road.getPoint31YTile(start.getSegmentStart()); + float estimatedDistance = (float) h(ctx, targetEndX, targetEndY, startX, startY); + end.distanceToEnd = start.distanceToEnd = estimatedDistance; + + graphDirectSegments.add(start); + graphReverseSegments.add(end); + + // Extract & analyze segment with min(f(x)) from queue while final segment is not found + boolean inverse = false; + boolean init = false; + + PriorityQueue graphSegments; + if(inverse) { + graphSegments = graphReverseSegments; + } else { + graphSegments = graphDirectSegments; + } + while (!graphSegments.isEmpty()) { + RouteSegment segment = graphSegments.poll(); + ctx.visitedSegments++; + // for debug purposes + if (ctx.visitor != null) { +// ctx.visitor.visitSegment(segment, true); + } + updateCalculationProgress(ctx, graphDirectSegments, graphReverseSegments); + boolean routeFound = false; + if (!inverse) { + routeFound = processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY, + segment, visitedOppositeSegments); + } else { + routeFound = processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment, + visitedDirectSegments); + } + if (graphReverseSegments.isEmpty() || graphDirectSegments.isEmpty() || routeFound) { + break; + } + if(runRecalculation) { + // nothing to do + inverse = false; + } else if (!init) { + inverse = !inverse; + init = true; + } else if (ctx.planRouteIn2Directions()) { + inverse = nonHeuristicSegmentsComparator.compare(graphDirectSegments.peek(), graphReverseSegments.peek()) > 0; + if (graphDirectSegments.size() * 1.3 > graphReverseSegments.size()) { + inverse = true; + } else if (graphDirectSegments.size() < 1.3 * graphReverseSegments.size()) { + inverse = false; + } + } else { + // different strategy : use onedirectional graph + inverse = ctx.getPlanRoadDirection() < 0; + } + if (inverse) { + graphSegments = graphReverseSegments; + } else { + graphSegments = graphDirectSegments; + } + // check if interrupted + if(ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) { + throw new InterruptedException("Route calculation interrupted"); + } + } + println("Result is found"); + printDebugMemoryInformation(ctx, graphDirectSegments, graphReverseSegments, visitedDirectSegments, visitedOppositeSegments); + } + + private void updateCalculationProgress(final RoutingContext ctx, PriorityQueue graphDirectSegments, + PriorityQueue graphReverseSegments) { + if(ctx.calculationProgress != null) { + ctx.calculationProgress.reverseSegmentQueueSize = graphReverseSegments.size(); + ctx.calculationProgress.directSegmentQueueSize = graphDirectSegments.size(); + RouteSegment dirPeek = graphDirectSegments.peek(); + if(dirPeek != null) { + ctx.calculationProgress.distanceFromBegin = + Math.max(dirPeek.distanceFromStart, ctx.calculationProgress.distanceFromBegin); + } + RouteSegment revPeek = graphReverseSegments.peek(); + if(revPeek != null) { + ctx.calculationProgress.distanceFromEnd = + Math.max(revPeek.distanceFromStart, ctx.calculationProgress.distanceFromEnd); + } + } + } + + + private double h(final RoutingContext ctx, int targetEndX, int targetEndY, + int startX, int startY) { + double distance = squareRootDist(startX, startY, targetEndX, targetEndY); + return distance / ctx.getRouter().getMaxDefaultSpeed(); + } + + protected static double h(RoutingContext ctx, double distToFinalPoint, RouteSegment next) { + double result = distToFinalPoint / ctx.getRouter().getMaxDefaultSpeed(); + return result; + } + + private static void println(String logMsg) { +// log.info(logMsg); + System.out.println(logMsg); + } + + private static void printInfo(String logMsg) { + log.warn(logMsg); + } + + public void printDebugMemoryInformation(RoutingContext ctx, PriorityQueue graphDirectSegments, PriorityQueue graphReverseSegments, + TLongObjectHashMap visitedDirectSegments,TLongObjectHashMap visitedOppositeSegments) { + printInfo("Time to calculate : " + (System.nanoTime() - ctx.timeToCalculate) / 1e6 + ", time to load : " + ctx.timeToLoad / 1e6 + ", time to load headers : " + ctx.timeToLoadHeaders / 1e6); + int maxLoadedTiles = Math.max(ctx.maxLoadedTiles, ctx.getCurrentlyLoadedTiles()); + printInfo("Current loaded tiles : " + ctx.getCurrentlyLoadedTiles() + ", maximum loaded tiles " + maxLoadedTiles); + printInfo("Loaded tiles " + ctx.loadedTiles + " (distinct "+ctx.distinctLoadedTiles+ "), unloaded tiles " + ctx.unloadedTiles + + ", loaded more than once same tiles " + + ctx.loadedPrevUnloadedTiles ); + printInfo("Visited roads, " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments); + if (graphDirectSegments != null && graphReverseSegments != null) { + printInfo("Priority queues sizes : " + graphDirectSegments.size() + "/" + graphReverseSegments.size()); + } + if (visitedDirectSegments != null && visitedOppositeSegments != null) { + printInfo("Visited segments sizes: " + visitedDirectSegments.size() + "/" + visitedOppositeSegments.size()); + } + + } + + + private boolean processRouteSegment(final RoutingContext ctx, boolean reverseWaySearch, + PriorityQueue graphSegments, TLongObjectHashMap visitedSegments, int targetEndX, int targetEndY, + RouteSegment segment, TLongObjectHashMap oppositeSegments) throws IOException { + // Always start from segmentStart (!), not from segmentEnd + // It makes difference only for the first start segment + // Middle point will always be skipped from observation considering already visited + final RouteDataObject road = segment.road; + final int middle = segment.getSegmentStart(); + float obstaclePlusTime = 0; + float obstacleMinusTime = 0; + + + // This is correct way of checking but it has problem with relaxing strategy +// long ntf = (segment.road.getId() << ROUTE_POINTS) + segment.segmentStart; +// visitedSegments.put(ntf, segment); +// if (oppositeSegments.contains(ntf) && oppositeSegments.get(ntf) != null) { +// RouteSegment opposite = oppositeSegments.get(ntf); +// if (opposite.segmentStart == segment.segmentStart) { + // if (reverseWaySearch) { + // reverse : segment.parentSegmentEnd - segment.parentRoute + // } else { + // reverse : opposite.parentSegmentEnd - oppositie.parentRoute + // } +// return true; +// } +// } + + // 0. mark route segment as visited + long nt = (road.getId() << ROUTE_POINTS) + middle; + // avoid empty segments to connect but mark the point as visited + visitedSegments.put(nt, null); + + int oneway = ctx.getRouter().isOneWay(road); + boolean minusAllowed; + boolean plusAllowed; + if(ctx.firstRoadId == nt) { + if(ctx.firstRoadDirection < 0) { + obstaclePlusTime += 500; + } else if(ctx.firstRoadDirection > 0) { + obstacleMinusTime += 500; + } + } + if (!reverseWaySearch) { + minusAllowed = oneway <= 0; + plusAllowed = oneway >= 0; + } else { + minusAllowed = oneway >= 0; + plusAllowed = oneway <= 0; + } + + // +/- diff from middle point + int d = plusAllowed ? 1 : -1; + if(segment.parentRoute != null) { + if(plusAllowed && middle < segment.getRoad().getPointsLength() - 1) { + obstaclePlusTime = (float) ctx.getRouter().calculateTurnTime(segment, segment.getRoad().getPointsLength() - 1, + segment.parentRoute, segment.parentSegmentEnd); + } + if(minusAllowed && middle > 0) { + obstacleMinusTime = (float) ctx.getRouter().calculateTurnTime(segment, 0, + segment.parentRoute, segment.parentSegmentEnd); + } + } + // Go through all point of the way and find ways to continue + // ! Actually there is small bug when there is restriction to move forward on way (it doesn't take into account) + float posSegmentDist = 0; + float negSegmentDist = 0; + while (minusAllowed || plusAllowed) { + // 1. calculate point not equal to middle + // (algorithm should visit all point on way if it is not oneway) + int segmentEnd = middle + d; + boolean positive = d > 0; + if (!minusAllowed && d > 0) { + d++; + } else if (!plusAllowed && d < 0) { + d--; + } else { + if (d <= 0) { + d = -d + 1; + } else { + d = -d; + } + } + if (segmentEnd < 0) { + minusAllowed = false; + continue; + } + if (segmentEnd >= road.getPointsLength()) { + plusAllowed = false; + continue; + } + // if we found end point break cycle + long nts = (road.getId() << ROUTE_POINTS) + segmentEnd; + visitedSegments.put(nts, segment); + + // 2. calculate point and try to load neighbor ways if they are not loaded + int x = road.getPoint31XTile(segmentEnd); + int y = road.getPoint31YTile(segmentEnd); + if(positive) { + posSegmentDist += squareRootDist(x, y, + road.getPoint31XTile(segmentEnd - 1), road.getPoint31YTile(segmentEnd - 1)); + } else { + negSegmentDist += squareRootDist(x, y, + road.getPoint31XTile(segmentEnd + 1), road.getPoint31YTile(segmentEnd + 1)); + } + + // 2.1 calculate possible obstacle plus time + if(positive){ + double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentEnd); + if (obstacle < 0) { + plusAllowed = false; + continue; + } + obstaclePlusTime += obstacle; + } else { + double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentEnd); + if (obstacle < 0) { + minusAllowed = false; + continue; + } + obstacleMinusTime += obstacle; + } +// int overhead = 0; + // could be expensive calculation + int overhead = (ctx.visitedSegments - ctx.relaxedSegments ) * + STANDARD_ROAD_IN_QUEUE_OVERHEAD; + if(overhead > ctx.config.memoryLimitation * 0.95){ + throw new OutOfMemoryError("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb"); + } + RouteSegment next = ctx.loadRouteSegment(x, y, ctx.config.memoryLimitation - overhead); + // 3. get intersected ways + if (next != null) { + // TO-DO U-Turn + if((next == segment || next.road.id == road.id) && next.next == null) { + // simplification if there is no real intersection + continue; + } + // Using A* routing algorithm + // g(x) - calculate distance to that point and calculate time + + float priority = ctx.getRouter().defineSpeedPriority(road); + float speed = ctx.getRouter().defineSpeed(road) * priority; + if (speed == 0) { + speed = ctx.getRouter().getMinDefaultSpeed() * priority; + } + float distOnRoadToPass = positive? posSegmentDist : negSegmentDist; + float distStartObstacles = segment.distanceFromStart + ( positive ? obstaclePlusTime : obstacleMinusTime) + + distOnRoadToPass / speed; + + float distToFinalPoint = (float) squareRootDist(x, y, targetEndX, targetEndY); + boolean routeFound = processIntersections(ctx, graphSegments, visitedSegments, oppositeSegments, + distStartObstacles, distToFinalPoint, segment, segmentEnd, next, reverseWaySearch); + if(routeFound){ + return routeFound; + } + + } + } + return false; + } + + + private boolean proccessRestrictions(RoutingContext ctx, RouteDataObject road, RouteSegment inputNext, boolean reverseWay) { + ctx.segmentsToVisitPrescripted.clear(); + ctx.segmentsToVisitNotForbidden.clear(); + boolean exclusiveRestriction = false; + RouteSegment next = inputNext; + if (!reverseWay && road.getRestrictionLength() == 0) { + return false; + } + if(!ctx.getRouter().restrictionsAware()) { + return false; + } + while (next != null) { + int type = -1; + if (!reverseWay) { + for (int i = 0; i < road.getRestrictionLength(); i++) { + if (road.getRestrictionId(i) == next.road.id) { + type = road.getRestrictionType(i); + break; + } + } + } else { + for (int i = 0; i < next.road.getRestrictionLength(); i++) { + int rt = next.road.getRestrictionType(i); + long restrictedTo = next.road.getRestrictionId(i); + if (restrictedTo == road.id) { + type = rt; + break; + } + + // Check if there is restriction only to the other than current road + if (rt == MapRenderingTypes.RESTRICTION_ONLY_RIGHT_TURN || rt == MapRenderingTypes.RESTRICTION_ONLY_LEFT_TURN + || rt == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) { + // check if that restriction applies to considered junk + RouteSegment foundNext = inputNext; + while (foundNext != null) { + if (foundNext.getRoad().id == restrictedTo) { + break; + } + foundNext = foundNext.next; + } + if (foundNext != null) { + type = REVERSE_WAY_RESTRICTION_ONLY; // special constant + } + } + } + } + if (type == REVERSE_WAY_RESTRICTION_ONLY) { + // next = next.next; continue; + } else if (type == -1 && exclusiveRestriction) { + // next = next.next; continue; + } else if (type == MapRenderingTypes.RESTRICTION_NO_LEFT_TURN || type == MapRenderingTypes.RESTRICTION_NO_RIGHT_TURN + || type == MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON || type == MapRenderingTypes.RESTRICTION_NO_U_TURN) { + // next = next.next; continue; + } else if (type == -1) { + // case no restriction + ctx.segmentsToVisitNotForbidden.add(next); + } else { + // case exclusive restriction (only_right, only_straight, ...) + // 1. in case we are going backward we should not consider only_restriction + // as exclusive because we have many "in" roads and one "out" + // 2. in case we are going forward we have one "in" and many "out" + if (!reverseWay) { + exclusiveRestriction = true; + ctx.segmentsToVisitNotForbidden.clear(); + ctx.segmentsToVisitPrescripted.add(next); + } else { + ctx.segmentsToVisitNotForbidden.add(next); + } + } + next = next.next; + } + ctx.segmentsToVisitPrescripted.addAll(ctx.segmentsToVisitNotForbidden); + return true; + } + + + + + private boolean processIntersections(RoutingContext ctx, PriorityQueue graphSegments, + TLongObjectHashMap visitedSegments, TLongObjectHashMap oppositeSegments, + float distFromStart, float distToFinalPoint, + RouteSegment segment, int segmentEnd, RouteSegment inputNext, + boolean reverseWay) { + + boolean thereAreRestrictions = proccessRestrictions(ctx, segment.road, inputNext, reverseWay); + Iterator nextIterator = null; + if (thereAreRestrictions) { + nextIterator = ctx.segmentsToVisitPrescripted.iterator(); + } + // Calculate possible ways to put into priority queue + RouteSegment next = inputNext; + boolean hasNext = nextIterator == null || nextIterator.hasNext(); + while (hasNext) { + if (nextIterator != null) { + next = nextIterator.next(); + } + long nts = (next.road.getId() << ROUTE_POINTS) + next.getSegmentStart(); + + // 1. Check if opposite segment found so we can stop calculations + if (oppositeSegments.contains(nts) && oppositeSegments.get(nts) != null) { + // restrictions checked + RouteSegment opposite = oppositeSegments.get(nts); + // additional check if opposite way not the same as current one + if (next.getSegmentStart() != segmentEnd || + opposite.getRoad().getId() != segment.getRoad().getId()) { + FinalRouteSegment frs = new FinalRouteSegment(segment.getRoad(), segment.getSegmentStart()); + float distStartObstacles = segment.distanceFromStart; + frs.setParentRoute(segment.getParentRoute()); + frs.setParentSegmentEnd(segment.getParentSegmentEnd()); + frs.reverseWaySearch = reverseWay; + frs.distanceFromStart = opposite.distanceFromStart + distStartObstacles; + RouteSegment op = new RouteSegment(segment.getRoad(), segmentEnd); + op.setParentRoute(opposite); + op.setParentSegmentEnd(next.getSegmentStart()); + frs.distanceToEnd = 0; + frs.opposite = op; + ctx.finalRouteSegment = frs; + return true; + } + } + // road.id could be equal on roundabout, but we should accept them + boolean alreadyVisited = visitedSegments.contains(nts); + if (!alreadyVisited) { + float distanceToEnd = (float) h(ctx, distToFinalPoint, next); + if (next.parentRoute == null + || ctx.roadPriorityComparator(next.distanceFromStart, next.distanceToEnd, distFromStart, distanceToEnd) > 0) { + if (next.parentRoute != null) { + // already in queue remove it + if (!graphSegments.remove(next)) { + // exist in different queue! + RouteSegment cpy = new RouteSegment(next.getRoad(), next.getSegmentStart()); + next = cpy; + } + } + next.distanceFromStart = distFromStart; + next.distanceToEnd = distanceToEnd; + // put additional information to recover whole route after + next.setParentRoute(segment); + next.setParentSegmentEnd(segmentEnd); + graphSegments.add(next); + } + if (ctx.visitor != null) { +// ctx.visitor.visitSegment(next, false); + } + } else { + // the segment was already visited! We need to follow better route if it exists + // that is very strange situation and almost exception (it can happen when we underestimate distnceToEnd) + if (distFromStart < next.distanceFromStart && next.road.id != segment.road.id) { + // That code is incorrect (when segment is processed itself, + // then it tries to make wrong u-turn) - + // this situation should be very carefully checked in future (seems to be fixed) + // System.out.println(segment.getRoad().getName() + " " + next.getRoad().getName()); + // System.out.println(next.distanceFromStart + " ! " + distFromStart); + next.distanceFromStart = distFromStart; + next.setParentRoute(segment); + next.setParentSegmentEnd(segmentEnd); + if (ctx.visitor != null) { +// ctx.visitor.visitSegment(next, next.getSegmentStart(), false); + } + } + } + + // iterate to next road + if (nextIterator == null) { + next = next.next; + hasNext = next != null; + } else { + hasNext = nextIterator.hasNext(); + } + } + return false; + } + + + + /*public */static int roadPriorityComparator(double o1DistanceFromStart, double o1DistanceToEnd, + double o2DistanceFromStart, double o2DistanceToEnd, double heuristicCoefficient ) { + // f(x) = g(x) + h(x) --- g(x) - distanceFromStart, h(x) - distanceToEnd (not exact) + return Double.compare(o1DistanceFromStart + heuristicCoefficient * o1DistanceToEnd, + o2DistanceFromStart + heuristicCoefficient * o2DistanceToEnd); + } + +} diff --git a/OsmAnd-java/src/net/osmand/router/GeneralRouter.java b/OsmAnd-java/src/net/osmand/router/GeneralRouter.java new file mode 100644 index 0000000000..69097e9918 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/GeneralRouter.java @@ -0,0 +1,349 @@ +package net.osmand.router; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + + +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; +import net.osmand.binary.RouteDataObject; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.util.MapUtils; + +public class GeneralRouter extends VehicleRouter { + public static final String USE_SHORTEST_WAY = "short_way"; + public static final String AVOID_FERRIES = "avoid_ferries"; + public static final String AVOID_TOLL = "avoid_toll"; + public static final String AVOID_MOTORWAY = "avoid_motorway"; + public static final String AVOID_UNPAVED = "avoid_unpaved"; + public static final String PREFER_MOTORWAYS = "prefer_motorway"; + + public Map highwaySpeed ; + public Map highwayPriorities ; + public Map avoid ; + public Map obstacles; + public Map routingObstacles; + public Map attributes; + + + private GeneralRouterProfile profile; + + // cached values + private boolean restrictionsAware = true; + private float leftTurn; + private float roundaboutTurn; + private float rightTurn; + private boolean onewayAware = true; + private boolean followSpeedLimitations = true; + private float minDefaultSpeed = 10; + private float maxDefaultSpeed = 10; + + public enum GeneralRouterProfile { + CAR, + PEDESTRIAN, + BICYCLE + } + + public GeneralRouter(GeneralRouterProfile profile, Map attributes) { + this.attributes = new LinkedHashMap(attributes); + this.profile = profile; + highwaySpeed = new LinkedHashMap(); + highwayPriorities = new LinkedHashMap(); + avoid = new LinkedHashMap(); + obstacles = new LinkedHashMap(); + routingObstacles = new LinkedHashMap(); + Iterator> e = attributes.entrySet().iterator(); + while(e.hasNext()){ + Entry next = e.next(); + addAttribute(next.getKey(), next.getValue()); + } + } + + public GeneralRouter(GeneralRouter pr, Map attributes) { + this.highwaySpeed = new LinkedHashMap(pr.highwaySpeed); + this.highwayPriorities = new LinkedHashMap(pr.highwayPriorities); + this.avoid = new LinkedHashMap(pr.avoid); + this.obstacles = new LinkedHashMap(pr.obstacles); + this.routingObstacles = new LinkedHashMap(pr.routingObstacles); + this.attributes = new LinkedHashMap(); + this.profile = pr.profile; + Iterator> e = attributes.entrySet().iterator(); + while(e.hasNext()){ + Entry next = e.next(); + addAttribute(next.getKey(), next.getValue()); + } + + } + + public void addAttribute(String k, String v) { + attributes.put(k, v); + if(k.equals("restrictionsAware")) { + restrictionsAware = parseSilentBoolean(v, restrictionsAware); + } else if(k.equals("onewayAware")) { + onewayAware = parseSilentBoolean(v, onewayAware); + } else if(k.equals("followSpeedLimitations")) { + followSpeedLimitations = parseSilentBoolean(v, followSpeedLimitations); + } else if(k.equals("leftTurn")) { + leftTurn = parseSilentFloat(v, leftTurn); + } else if(k.equals("rightTurn")) { + rightTurn = parseSilentFloat(v, rightTurn); + } else if(k.equals("roundaboutTurn")) { + roundaboutTurn = parseSilentFloat(v, roundaboutTurn); + } else if(k.equals("minDefaultSpeed")) { + minDefaultSpeed = parseSilentFloat(v, minDefaultSpeed * 3.6f) / 3.6f; + } else if(k.equals("maxDefaultSpeed")) { + maxDefaultSpeed = parseSilentFloat(v, maxDefaultSpeed * 3.6f) / 3.6f; + } + } + + @Override + public boolean acceptLine(RouteDataObject way) { + int[] types = way.getTypes(); + RouteRegion reg = way.region; + return acceptLine(types, reg); + } + + public boolean acceptLine(int[] types, RouteRegion reg) { + if(!highwaySpeed.containsKey(RouteDataObject.getHighway(types, reg))) { + boolean accepted = false; + for (int i = 0; i < types.length; i++) { + RouteTypeRule r = reg.quickGetEncodingRule(types[i]); + Float sp = highwaySpeed.get(r.getTag()+"$"+r.getValue()); + if(sp != null){ + if(sp.floatValue() > 0) { + accepted = true; + } + break; + } + } + if(!accepted) { + return false; + } + } + + + for(int i=0; i 0) { + return m; + } + } + + Float value = null; + for (int i = 0; i < road.types.length; i++) { + RouteTypeRule r = road.region.quickGetEncodingRule(road.types[i]); + if(highwaySpeed.containsKey(r.getTag()+"$"+r.getValue())){ + value = highwaySpeed.get(r.getTag()+"$"+r.getValue()); + break; + } + } + if (value == null) { + return getMinDefaultSpeed(); + } + return value / 3.6f; + } + + @Override + public float defineSpeedPriority(RouteDataObject road) { + float priority = 1; + for (int i = 0; i < road.types.length; i++) { + RouteTypeRule r = road.region.quickGetEncodingRule(road.types[i]); + if(highwayPriorities.containsKey(r.getTag()+"$"+r.getValue())){ + priority *= highwayPriorities.get(r.getTag()+"$"+r.getValue()); + } + } + return priority; + } + + @Override + public float getMinDefaultSpeed() { + return minDefaultSpeed; + } + + @Override + public float getMaxDefaultSpeed() { + return maxDefaultSpeed ; + } + + + public double getLeftTurn() { + return leftTurn; + } + + public double getRightTurn() { + return rightTurn; + } + public double getRoundaboutTurn() { + return roundaboutTurn; + } + @Override + public double calculateTurnTime(RouteSegment segment, int segmentEnd, RouteSegment prev, int prevSegmentEnd) { + int[] pt = prev.getRoad().getPointTypes(prevSegmentEnd); + if(pt != null) { + RouteRegion reg = prev.getRoad().region; + for(int i=0; i 0 && !prev.getRoad().roundabout() && segment.getRoad().roundabout()) { + return rt; + } + if (getLeftTurn() > 0 || getRightTurn() > 0) { + double a1 = segment.getRoad().directionRoute(segment.getSegmentStart(), segment.getSegmentStart() < segmentEnd); + double a2 = prev.getRoad().directionRoute(prevSegmentEnd, prevSegmentEnd < prev.getSegmentStart()); + double diff = Math.abs(MapUtils.alignAngleDifference(a1 - a2 - Math.PI)); + // more like UT + if (diff > 2 * Math.PI / 3) { + return getLeftTurn(); + } else if (diff > Math.PI / 2) { + return getRightTurn(); + } + return 0; + } + return 0; + } + + private void specialize(String specializationTag, Map m){ + ArrayList ks = new ArrayList(m.keySet()); + for(String s : ks){ + if(s.startsWith(specializationTag +":")) { + String tagName = s.substring((specializationTag +":").length()); + m.put(tagName, m.get(s)); + } + } + } + + @Override + public GeneralRouter specifyParameter(String specializationTag) { + Map attrs = new LinkedHashMap(attributes); + for(String s : attributes.keySet()){ + if(s.startsWith(specializationTag +":")) { + String tagName = s.substring((specializationTag +":").length()); + attrs.put(tagName, attributes.get(s)); + } + } + GeneralRouter gr = new GeneralRouter(this, attrs); + gr.specialize(specializationTag, gr.highwayPriorities); + gr.specialize(specializationTag, gr.highwaySpeed); + gr.specialize(specializationTag, gr.avoid); + gr.specialize(specializationTag, gr.obstacles); + gr.specialize(specializationTag, gr.routingObstacles); + gr.specialize(specializationTag, gr.attributes); + + return gr; + } + + @Override + public boolean containsAttribute(String attribute) { + return attributes.containsKey(attribute); + } + + @Override + public String getAttribute(String attribute) { + return attributes.get(attribute); + } + + +} + diff --git a/OsmAnd-java/src/net/osmand/router/NewGeneralRouter.java b/OsmAnd-java/src/net/osmand/router/NewGeneralRouter.java new file mode 100644 index 0000000000..c1ea8ab8c6 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/NewGeneralRouter.java @@ -0,0 +1,414 @@ +package net.osmand.router; + +import gnu.trove.list.array.TByteArrayList; +import gnu.trove.list.array.TIntArrayList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + + +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; +import net.osmand.binary.RouteDataObject; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.util.MapUtils; + +public class NewGeneralRouter extends VehicleRouter { + + public RouteAttributeContext roadSpeed ; + public RouteAttributeContext roadPriorities ; + public RouteAttributeContext access ; + public RouteAttributeContext obstacles; + public RouteAttributeContext routingObstacles; + public RouteAttributeContext oneway; + public Map attributes; + + private Map parameters = new LinkedHashMap(); + private Map universalRules = new LinkedHashMap(); + private Map> freeTagRules = new HashMap>(); + private Map> regionConvert = new LinkedHashMap>(); + + + private GeneralRouterProfile profile; + + // cached values + private boolean restrictionsAware = true; + private float leftTurn; + private float roundaboutTurn; + private float rightTurn; + private float minDefaultSpeed = 10; + private float maxDefaultSpeed = 10; + + public enum RoutingParameterType { + NUMERIC, + BOOLEAN, + SYMBOLIC + } + public enum GeneralRouterProfile { + CAR, + PEDESTRIAN, + BICYCLE + } + + public NewGeneralRouter(GeneralRouterProfile profile, Map attributes) { + this.attributes = new LinkedHashMap(); + this.profile = profile; + Iterator> e = attributes.entrySet().iterator(); + while(e.hasNext()){ + Entry next = e.next(); + addAttribute(next.getKey(), next.getValue()); + } + } + + public void addAttribute(String k, String v) { + attributes.put(k, v); + if(k.equals("restrictionsAware")) { + restrictionsAware = parseSilentBoolean(v, restrictionsAware); + } else if(k.equals("leftTurn")) { + leftTurn = parseSilentFloat(v, leftTurn); + } else if(k.equals("rightTurn")) { + rightTurn = parseSilentFloat(v, rightTurn); + } else if(k.equals("roundaboutTurn")) { + roundaboutTurn = parseSilentFloat(v, roundaboutTurn); + } else if(k.equals("minDefaultSpeed")) { + minDefaultSpeed = parseSilentFloat(v, minDefaultSpeed * 3.6f) / 3.6f; + } else if(k.equals("maxDefaultSpeed")) { + maxDefaultSpeed = parseSilentFloat(v, maxDefaultSpeed * 3.6f) / 3.6f; + } + } + + @Override + public boolean acceptLine(RouteDataObject way) { + int[] utypes = convert(way.region, way.getTypes()); + int res = access.evaluateInt(utypes, 0); + return res >= 0; + } + + private int[] convert(RouteRegion reg, int[] types) { + int[] utypes = new int[types.length]; + Map map = regionConvert.get(reg); + if(map == null){ + map = new HashMap(); + regionConvert.put(reg, map); + } + for(int k = 0; k < types.length; k++) { + Integer nid = map.get(types[k]); + if(nid == null){ + RouteTypeRule r = reg.quickGetEncodingRule(types[k]); + nid = registerRule(r.getTag(), r.getValue()); + map.put(types[k], nid); + } + utypes[k] = nid; + } + Arrays.sort(utypes); + return utypes; + } + + public int registerRule(String tag, String value) { + String key = tag +"$"+value; + if(universalRules.containsKey(key)) { + return universalRules.get(key); + } + universalRules.put(key, universalRules.size()); + return universalRules.size() - 1; + } + + public void build(){ + freeTagRules.clear(); + + roadSpeed.newEvaluationContext(); + roadPriorities.newEvaluationContext(); + access.newEvaluationContext(); + obstacles.newEvaluationContext(); + routingObstacles.newEvaluationContext(); + oneway.newEvaluationContext(); + } + + public void registerFreeTagRule(RouteEvaluationRule r, String tag) { + if(!freeTagRules.containsKey(tag)) { + freeTagRules.put(tag, new ArrayList()); + } + freeTagRules.get(tag).add(r); + Iterator> it = universalRules.entrySet().iterator(); + while (it.hasNext()) { + Entry e = it.next(); + String key = e.getKey(); + if (key.startsWith(tag + "$")) { + r.insertType(e.getValue(), false); + } + if (tag.startsWith("-") && universalRules.containsKey(tag.substring(1) + "$")) { + r.insertType(e.getValue(), true); + } + } + } + + private void updateFreeTagRules() { + + } + + private void updateFreeTagRules(List flist, int value, boolean not) { + + + } + + @Override + public boolean restrictionsAware() { + return restrictionsAware; + } + + @Override + public float defineObstacle(RouteDataObject road, int point) { + int[] ts = road.getPointTypes(point); + if(ts != null) { + + } + // TODO + return 0; + } + + @Override + public float defineRoutingObstacle(RouteDataObject road, int point) { + // TODO + return 0; + } + + @Override + public int isOneWay(RouteDataObject road) { + // TODO + return 0; + } + + + private static boolean parseSilentBoolean(String t, boolean v) { + if (t == null || t.length() == 0) { + return v; + } + return Boolean.parseBoolean(t); + } + + private static float parseSilentFloat(String t, float v) { + if (t == null || t.length() == 0) { + return v; + } + return Float.parseFloat(t); + } + + @Override + public float defineSpeed(RouteDataObject road) { + // TODO + return 0; + } + + @Override + public float defineSpeedPriority(RouteDataObject road) { + return 0; + } + + @Override + public float getMinDefaultSpeed() { + return minDefaultSpeed; + } + + @Override + public float getMaxDefaultSpeed() { + return maxDefaultSpeed ; + } + + + public double getLeftTurn() { + return leftTurn; + } + + public double getRightTurn() { + return rightTurn; + } + public double getRoundaboutTurn() { + return roundaboutTurn; + } + @Override + public double calculateTurnTime(RouteSegment segment, int segmentEnd, RouteSegment prev, int prevSegmentEnd) { + int[] pt = prev.getRoad().getPointTypes(prevSegmentEnd); + if(pt != null) { + RouteRegion reg = prev.getRoad().region; + for(int i=0; i 0 && !prev.getRoad().roundabout() && segment.getRoad().roundabout()) { + return rt; + } + if (getLeftTurn() > 0 || getRightTurn() > 0) { + double a1 = segment.getRoad().directionRoute(segment.getSegmentStart(), segment.getSegmentStart() < segmentEnd); + double a2 = prev.getRoad().directionRoute(prevSegmentEnd, prevSegmentEnd < prev.getSegmentStart()); + double diff = Math.abs(MapUtils.alignAngleDifference(a1 - a2 - Math.PI)); + // more like UT + if (diff > 2 * Math.PI / 3) { + return getLeftTurn(); + } else if (diff > Math.PI / 2) { + return getRightTurn(); + } + return 0; + } + return 0; + } + + + @Override + public NewGeneralRouter specifyParameter(String parameter) { + // TODO + return this; + } + + @Override + public boolean containsAttribute(String attribute) { + return attributes.containsKey(attribute); + } + + @Override + public String getAttribute(String attribute) { + return attributes.get(attribute); + } + + + public static class RoutingParameter { + public String id; + public String name; + public String description; + public RoutingParameterType type; + public String[] possibleValues; + public String[] possibleValueDescriptions; + public Object value; + } + + private class RouteEvaluationRule { + + private List tag = new ArrayList(); + private List values = new ArrayList(); + private List parameters = new ArrayList() ; + + //// evaluation variables + private boolean parameterValue = true; + private TByteArrayList notType = new TByteArrayList(); + private TIntArrayList sortedTypeArrays = new TIntArrayList(); + + public void newEvaluationContext(){ + evaluateParameterExpr(); + sortedTypeArrays.clear(); + notType.clear(); + for(int i = 0; i defParams = NewGeneralRouter.this.parameters; + for(String p : parameters) { + boolean not = false; + if(p.startsWith("-")) { + not = true; + p = p.substring(1); + } + boolean val = false; + if(defParams.containsKey(p)) { + RoutingParameter t = defParams.get(p); + val = t.type == RoutingParameterType.BOOLEAN && t.value != null && ((Boolean)t.value).booleanValue(); + } + if(not && val){ + parameterValue = false; + break; + } else if(!not && !val){ + parameterValue = false; + break; + } + + } + } + + public boolean isAlwaysFalse() { + return !parameterValue; + } + + public boolean isAlwaysTrue() { + return parameterValue && isConst(); + } + + public boolean isConst(){ + return tag == null; + } + + public boolean matches(int[] types) { + if(isAlwaysFalse()){ + return false; + } + // TODO + // TODO + return true; + } + + } + + private class RouteAttributeContext { + List rules = new ArrayList(); + List values = new ArrayList(); + + public void newEvaluationContext(){ + for (int k = 0; k < rules.size(); k++) { + rules.get(k).newEvaluationContext(); + } + } + + public Object evaluate(int[] types) { + for (int k = 0; k < rules.size(); k++) { + if(rules.get(k).matches(types)){ + return values.get(k); + } + } + return null; + } + + public int evaluateInt(int[] types, int defValue) { + Object o = evaluate(types); + if(o == null) { + return defValue; + } + return ((Number)o).intValue(); + } + + public float evaluateFloat(int[] types, float defValue) { + Object o = evaluate(types); + if(o == null) { + return defValue; + } + return ((Float)o).intValue(); + } + + } + + +} + diff --git a/OsmAnd-java/src/net/osmand/router/RouteCalculationProgress.java b/OsmAnd-java/src/net/osmand/router/RouteCalculationProgress.java new file mode 100644 index 0000000000..8e86537c99 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/RouteCalculationProgress.java @@ -0,0 +1,18 @@ +package net.osmand.router; + +public class RouteCalculationProgress { + + public int segmentNotFound = -1; + public float distanceFromBegin; + public int directSegmentQueueSize; + public float distanceFromEnd; + public int reverseSegmentQueueSize; + public float totalEstimatedDistance = 0; + + public float routingCalculatedTime = 0; + public int loadedTiles = 0; + public int visitedSegments = 0; + + public boolean isCancelled; + +} diff --git a/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java b/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java new file mode 100644 index 0000000000..4c03aa413c --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/RoutePlannerFrontEnd.java @@ -0,0 +1,279 @@ +package net.osmand.router; + + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import net.osmand.PlatformUtil; +import net.osmand.binary.BinaryMapRouteReaderAdapter; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.RouteDataObject; +import net.osmand.data.LatLon; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + +public class RoutePlannerFrontEnd { + + private boolean useOldVersion; + protected static final Log log = PlatformUtil.getLog(BinaryRoutePlannerOld.class); + + public RoutePlannerFrontEnd(boolean useOldVersion) { + this.useOldVersion = useOldVersion; + } + + private static double squareRootDist(int x1, int y1, int x2, int y2) { + // translate into meters + double dy = MapUtils.convert31YToMeters(y1, y2); + double dx = MapUtils.convert31XToMeters(x1, x2); + return Math.sqrt(dx * dx + dy * dy); +// return measuredDist(x1, y1, x2, y2); + } + + private static double calculateProjection(int xA, int yA, int xB, int yB, int xC, int yC) { + // Scalar multiplication between (AB, AC) + double multiple = MapUtils.convert31XToMeters(xB, xA) * MapUtils.convert31XToMeters(xC, xA) + + MapUtils.convert31YToMeters(yB, yA) * MapUtils.convert31YToMeters(yC, yA); + return multiple; + } + private static double squareDist(int x1, int y1, int x2, int y2) { + // translate into meters + double dy = MapUtils.convert31YToMeters(y1, y2); + double dx = MapUtils. convert31XToMeters(x1, x2); + return dx * dx + dy * dy; + } + + public RouteSegment findRouteSegment(double lat, double lon, RoutingContext ctx) throws IOException { + int px = MapUtils.get31TileNumberX(lon); + int py = MapUtils.get31TileNumberY(lat); + ArrayList dataObjects = new ArrayList(); + ctx.loadTileData(px, py, 17, dataObjects); + if (dataObjects.isEmpty()) { + ctx.loadTileData(px, py, 15, dataObjects); + } + RouteSegment road = null; + double sdist = 0; + int foundProjX = 0; + int foundProjY = 0; + + for (RouteDataObject r : dataObjects) { + if (r.getPointsLength() > 1) { + for (int j = 1; j < r.getPointsLength(); j++) { + double mDist = squareRootDist(r.getPoint31XTile(j), r.getPoint31YTile(j), r.getPoint31XTile(j - 1), + r.getPoint31YTile(j - 1)); + int prx = r.getPoint31XTile(j); + int pry = r.getPoint31YTile(j); + double projection = calculateProjection(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), r.getPoint31XTile(j), + r.getPoint31YTile(j), px, py); + if (projection < 0) { + prx = r.getPoint31XTile(j - 1); + pry = r.getPoint31YTile(j - 1); + } else if (projection >= mDist * mDist) { + prx = r.getPoint31XTile(j); + pry = r.getPoint31YTile(j); + } else { + prx = (int) (r.getPoint31XTile(j - 1) + (r.getPoint31XTile(j) - r.getPoint31XTile(j - 1)) + * (projection / (mDist * mDist))); + pry = (int) (r.getPoint31YTile(j - 1) + (r.getPoint31YTile(j) - r.getPoint31YTile(j - 1)) + * (projection / (mDist * mDist))); + } + double currentsDist = squareDist(prx, pry, px, py); + if (road == null || currentsDist < sdist) { + RouteDataObject ro = new RouteDataObject(r); + road = new RouteSegment(ro, j); + ro.insert(j, prx, pry); + sdist = currentsDist; + foundProjX = prx; + foundProjY = pry; + } + } + } + } + if (road != null) { + // re-register the best road because one more point was inserted + ctx.registerRouteDataObject(road.getRoad()); + } + return road; + } + + public List searchRoute(final RoutingContext ctx, LatLon start, LatLon end, List intermediates, boolean leftSideNavigation) throws IOException, InterruptedException { + if(ctx.calculationProgress == null) { + ctx.calculationProgress = new RouteCalculationProgress(); + } + if((intermediates == null || intermediates.isEmpty()) && useOldVersion && ctx.nativeLib != null) { + ctx.startX = MapUtils.get31TileNumberX(start.getLongitude()); + ctx.startY = MapUtils.get31TileNumberY(start.getLatitude()); + ctx.targetX = MapUtils.get31TileNumberX(end.getLongitude()); + ctx.targetY = MapUtils.get31TileNumberY(end.getLatitude()); + List res = runNativeRouting(ctx, leftSideNavigation); + if(res != null) { + new RouteResultPreparation().printResults(ctx, start, end, res); + } + return res; + } + int indexNotFound = 0; + List points = new ArrayList(); + if(!addSegment(start, ctx, indexNotFound++, points)){ + return null; + } + if (intermediates != null) { + for (LatLon l : intermediates) { + if (!addSegment(l, ctx, indexNotFound++, points)) { + return null; + } + } + } + if(!addSegment(end, ctx, indexNotFound++, points)){ + return null; + } + List res = searchRoute(ctx, points, leftSideNavigation); + if(res != null) { + new RouteResultPreparation().printResults(ctx, start, end, res); + } + return res; + } + + private boolean addSegment(LatLon s, RoutingContext ctx, int indexNotFound, List res) throws IOException { + RouteSegment f = findRouteSegment(s.getLatitude(), s.getLongitude(), ctx); + if(f == null){ + ctx.calculationProgress.segmentNotFound = indexNotFound; + return false; + } else { + log.info("Route segment found " + f.getRoad().id + " " + f.getRoad().getName()); + res.add(f); + return true; + } + + } + + private List searchRouteInternalPrepare(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException { + ctx.targetX = end.road.getPoint31XTile(end.getSegmentStart()); + ctx.targetY = end.road.getPoint31YTile(end.getSegmentStart()); + ctx.startX = start.road.getPoint31XTile(start.getSegmentStart()); + ctx.startY = start.road.getPoint31YTile(start.getSegmentStart()); + if (ctx.nativeLib != null && useOldVersion) { + return runNativeRouting(ctx, leftSideNavigation); + } else { + refreshProgressDistance(ctx); + // Split into 2 methods to let GC work in between + if(useOldVersion) { + new BinaryRoutePlannerOld().searchRouteInternal(ctx, start, end); + } else { + ctx.finalRouteSegment = new BinaryRoutePlanner().searchRouteInternal(ctx, start, end); + } + // 4. Route is found : collect all segments and prepare result + return new RouteResultPreparation().prepareResult(ctx, ctx.finalRouteSegment, leftSideNavigation); + } + } + + private void refreshProgressDistance(RoutingContext ctx) { + if(ctx.calculationProgress != null) { + ctx.calculationProgress.distanceFromBegin = 0; + ctx.calculationProgress.distanceFromEnd = 0; + ctx.calculationProgress.reverseSegmentQueueSize = 0; + ctx.calculationProgress.directSegmentQueueSize = 0; + float rd = (float) squareRootDist(ctx.startX, ctx.startY, ctx.targetX, ctx.targetY); + float speed = 0.9f * ctx.config.router.getMaxDefaultSpeed(); + ctx.calculationProgress.totalEstimatedDistance = (float) (rd / speed); + } + + } + + private List runNativeRouting(final RoutingContext ctx, boolean leftSideNavigation) throws IOException { + refreshProgressDistance(ctx); + RouteRegion[] regions = ctx.reverseMap.keySet().toArray(new BinaryMapRouteReaderAdapter.RouteRegion[ctx.reverseMap.size()]); + RouteSegmentResult[] res = ctx.nativeLib.runNativeRouting(ctx.startX, ctx.startY, ctx.targetX, ctx.targetY, + ctx.config, regions, ctx.calculationProgress); + ArrayList result = new ArrayList(Arrays.asList(res)); + ctx.routingTime = ctx.calculationProgress.routingCalculatedTime; + ctx.visitedSegments = ctx.calculationProgress.visitedSegments; + ctx.loadedTiles = ctx.calculationProgress.loadedTiles; + return new RouteResultPreparation().prepareResult(ctx, leftSideNavigation, result); + } + + + private List searchRoute(final RoutingContext ctx, List points, boolean leftSideNavigation) throws IOException, InterruptedException { + if(points.size() > 2) { + ArrayList firstPartRecalculatedRoute = null; + ArrayList restPartRecalculatedRoute = null; + if (ctx.previouslyCalculatedRoute != null) { + List prev = ctx.previouslyCalculatedRoute; + long id = points.get(1).getRoad().id; + int ss = points.get(1).getSegmentStart(); + for (int i = 0; i < prev.size(); i++) { + RouteSegmentResult rsr = prev.get(i); + if (id == rsr.getObject().getId() && ss == rsr.getEndPointIndex()) { + firstPartRecalculatedRoute = new ArrayList(i + 1); + restPartRecalculatedRoute = new ArrayList(prev.size() - i); + for(int k = 0; k < prev.size(); k++) { + if(k <= i) { + firstPartRecalculatedRoute.add(prev.get(k)); + } else { + restPartRecalculatedRoute.add(prev.get(k)); + } + } + break; + } + } + } + List results = new ArrayList(); + for (int i = 0; i < points.size() - 1; i++) { + RoutingContext local = new RoutingContext(ctx); + if(i == 0) { + local.previouslyCalculatedRoute = firstPartRecalculatedRoute; + } + local.visitor = ctx.visitor; + local.calculationProgress = ctx.calculationProgress; + List res = searchRouteInternalPrepare(local, points.get(i), points.get(i + 1), leftSideNavigation); + + results.addAll(res); + ctx.distinctLoadedTiles += local.distinctLoadedTiles; + ctx.loadedTiles += local.loadedTiles; + ctx.visitedSegments += local.visitedSegments; + ctx.loadedPrevUnloadedTiles += local.loadedPrevUnloadedTiles; + ctx.timeToCalculate += local.timeToCalculate; + ctx.timeToLoad += local.timeToLoad; + ctx.timeToLoadHeaders += local.timeToLoadHeaders; + ctx.relaxedSegments += local.relaxedSegments; + ctx.routingTime += local.routingTime; + + local.unloadAllData(ctx); + if(restPartRecalculatedRoute != null) { + results.addAll(restPartRecalculatedRoute); + break; + } + } + ctx.unloadAllData(); + return results; + } + return searchRoute(ctx, points.get(0), points.get(1), leftSideNavigation); + } + + @SuppressWarnings("static-access") + private List searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException { + if(ctx.SHOW_GC_SIZE){ + long h1 = ctx.runGCUsedMemory(); + float mb = (1 << 20); + log.warn("Used before routing " + h1 / mb+ " actual"); + } + List result = searchRouteInternalPrepare(ctx, start, end, leftSideNavigation); + if (RoutingContext.SHOW_GC_SIZE) { + int sz = ctx.global.size; + log.warn("Subregion size " + ctx.subregionTiles.size() + " " + " tiles " + ctx.indexedSubregions.size()); + ctx.runGCUsedMemory(); + long h1 = ctx.runGCUsedMemory(); + ctx.unloadAllData(); + ctx.runGCUsedMemory(); + long h2 = ctx.runGCUsedMemory(); + float mb = (1 << 20); + log.warn("Unload context : estimated " + sz / mb + " ?= " + (h1 - h2) / mb + " actual"); + } + return result; + } + + + +} diff --git a/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java b/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java new file mode 100644 index 0000000000..19dfd4f533 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java @@ -0,0 +1,587 @@ +package net.osmand.router; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.RouteDataObject; +import net.osmand.data.LatLon; +import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.util.MapUtils; + +public class RouteResultPreparation { + + public static boolean PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true; + private static final float TURN_DEGREE_MIN = 45; + /** + * Helper method to prepare final result + */ + List prepareResult(RoutingContext ctx, FinalRouteSegment finalSegment,boolean leftside) throws IOException { + List result = convertFinalSegmentToResults(ctx, finalSegment); + prepareResult(ctx, leftside, result); + return result; + } + + List prepareResult(RoutingContext ctx, boolean leftside, List result) throws IOException { + validateAllPointsConnected(result); + splitRoadsAndAttachRoadSegments(ctx, result); + // calculate time + calculateTimeSpeed(ctx, result); + + addTurnInfo(leftside, result); + return result; + } + + private void calculateTimeSpeed(RoutingContext ctx, List result) throws IOException { + for (int i = 0; i < result.size(); i++) { + RouteSegmentResult rr = result.get(i); + RouteDataObject road = rr.getObject(); + double distOnRoadToPass = 0; + double speed = ctx.getRouter().defineSpeed(road); + if (speed == 0) { + speed = ctx.getRouter().getMinDefaultSpeed(); + } + boolean plus = rr.getStartPointIndex() < rr.getEndPointIndex(); + int next; + double distance = 0; + for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) { + next = plus ? j + 1 : j - 1; + double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next), + road.getPoint31YTile(next)); + distance += d; + double obstacle = ctx.getRouter().defineObstacle(road, j); + if (obstacle < 0) { + obstacle = 0; + } + distOnRoadToPass += d / speed + obstacle; + + } + // last point turn time can be added + // if(i + 1 < result.size()) { distOnRoadToPass += ctx.getRouter().calculateTurnTime(); } + rr.setSegmentTime((float) distOnRoadToPass); + rr.setSegmentSpeed((float) speed); + rr.setDistance((float) distance); + } + } + + private void splitRoadsAndAttachRoadSegments(RoutingContext ctx, List result) throws IOException { + for (int i = 0; i < result.size(); i++) { + if (ctx.checkIfMemoryLimitCritical(ctx.config.memoryLimitation)) { + ctx.unloadUnusedTiles(ctx.config.memoryLimitation); + } + RouteSegmentResult rr = result.get(i); + RouteDataObject road = rr.getObject(); + checkAndInitRouteRegion(ctx, road); + boolean plus = rr.getStartPointIndex() < rr.getEndPointIndex(); + int next; + for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) { + next = plus ? j + 1 : j - 1; + if (j == rr.getStartPointIndex()) { + attachRoadSegments(ctx, result, i, j, plus); + } + if (next != rr.getEndPointIndex()) { + attachRoadSegments(ctx, result, i, next, plus); + } + List attachedRoutes = rr.getAttachedRoutes(next); + if (next != rr.getEndPointIndex() && !rr.getObject().roundabout() && attachedRoutes != null) { + float before = rr.getBearing(next, !plus); + float after = rr.getBearing(next, plus); + boolean straight = Math.abs(MapUtils.degreesDiff(before + 180, after)) < TURN_DEGREE_MIN; + boolean isSplit = false; + // split if needed + for (RouteSegmentResult rs : attachedRoutes) { + double diff = MapUtils.degreesDiff(before + 180, rs.getBearingBegin()); + if (Math.abs(diff) <= TURN_DEGREE_MIN) { + isSplit = true; + } else if (!straight && Math.abs(diff) < 100) { + isSplit = true; + } + } + if (isSplit) { + int endPointIndex = rr.getEndPointIndex(); + RouteSegmentResult split = new RouteSegmentResult(rr.getObject(), next, endPointIndex); + split.copyPreattachedRoutes(rr, Math.abs(next - rr.getStartPointIndex())); + rr.setEndPointIndex(next); + result.add(i + 1, split); + i++; + // switch current segment to the splitted + rr = split; + } + } + } + } + } + + private void checkAndInitRouteRegion(RoutingContext ctx, RouteDataObject road) throws IOException { + BinaryMapIndexReader reader = ctx.reverseMap.get(road.region); + if(reader != null) { + reader.initRouteRegion(road.region); + } + } + + private void validateAllPointsConnected(List result) { + for (int i = 1; i < result.size(); i++) { + RouteSegmentResult rr = result.get(i); + RouteSegmentResult pr = result.get(i - 1); + double d = MapUtils.getDistance(pr.getPoint(pr.getEndPointIndex()), rr.getPoint(rr.getStartPointIndex())); + if (d > 0) { + System.err.println("Points are not connected : " + pr.getObject() + "(" + pr.getEndPointIndex() + ") -> " + rr.getObject() + + "(" + rr.getStartPointIndex() + ") " + d + " meters"); + } + } + } + + private List convertFinalSegmentToResults(RoutingContext ctx, FinalRouteSegment finalSegment) { + List result = new ArrayList(); + if (finalSegment != null) { + ctx.routingTime = finalSegment.distanceFromStart; + println("Routing calculated time distance " + finalSegment.distanceFromStart); + // Get results from opposite direction roads + RouteSegment segment = finalSegment.reverseWaySearch ? finalSegment : finalSegment.opposite.getParentRoute(); + int parentSegmentStart = finalSegment.reverseWaySearch ? finalSegment.opposite.getSegmentStart() : finalSegment.opposite.getParentSegmentEnd(); + while (segment != null) { + RouteSegmentResult res = new RouteSegmentResult(segment.road, parentSegmentStart, segment.getSegmentStart()); + parentSegmentStart = segment.getParentSegmentEnd(); + segment = segment.getParentRoute(); + addRouteSegmentToResult(result, res, false); + } + // reverse it just to attach good direction roads + Collections.reverse(result); + + segment = finalSegment.reverseWaySearch ? finalSegment.opposite.getParentRoute() : finalSegment; + int parentSegmentEnd = finalSegment.reverseWaySearch ? finalSegment.opposite.getParentSegmentEnd() : finalSegment.opposite.getSegmentStart(); + + while (segment != null) { + RouteSegmentResult res = new RouteSegmentResult(segment.road, segment.getSegmentStart(), parentSegmentEnd); + parentSegmentEnd = segment.getParentSegmentEnd(); + segment = segment.getParentRoute(); + // happens in smart recalculation + addRouteSegmentToResult(result, res, true); + } + Collections.reverse(result); + + } + return result; + } + + private void addRouteSegmentToResult(List result, RouteSegmentResult res, boolean reverse) { + if (res.getStartPointIndex() != res.getEndPointIndex()) { + if (result.size() > 0) { + RouteSegmentResult last = result.get(result.size() - 1); + if (last.getObject().id == res.getObject().id) { + if (combineTwoSegmentResult(res, last, reverse)) { + return; + } + } + } + result.add(res); + } + } + + private boolean combineTwoSegmentResult(RouteSegmentResult toAdd, RouteSegmentResult previous, + boolean reverse) { + boolean ld = previous.getEndPointIndex() > previous.getStartPointIndex(); + boolean rd = toAdd.getEndPointIndex() > toAdd.getStartPointIndex(); + if (rd == ld) { + if (toAdd.getStartPointIndex() == previous.getEndPointIndex() && !reverse) { + previous.setEndPointIndex(toAdd.getEndPointIndex()); + return true; + } else if (toAdd.getEndPointIndex() == previous.getStartPointIndex() && reverse) { + previous.setStartPointIndex(toAdd.getStartPointIndex()); + return true; + } + } + return false; + } + + void printResults(RoutingContext ctx, LatLon start, LatLon end, List result) { + float completeTime = 0; + float completeDistance = 0; + for(RouteSegmentResult r : result) { + completeTime += r.getSegmentTime(); + completeDistance += r.getDistance(); + } + + println("ROUTE : "); + double startLat = start.getLatitude(); + double startLon = start.getLongitude(); + double endLat = end.getLatitude(); + double endLon = end.getLongitude(); + StringBuilder add = new StringBuilder(); + add.append("loadedTiles = \"").append(ctx.loadedTiles).append("\" "); + add.append("visitedSegments = \"").append(ctx.visitedSegments).append("\" "); + add.append("complete_distance = \"").append(completeDistance).append("\" "); + add.append("complete_time = \"").append(completeTime).append("\" "); + add.append("routing_time = \"").append(ctx.routingTime).append("\" "); + println(MessageFormat.format("", startLat + + "", startLon + "", endLat + "", endLon + "", ctx.config.routerName, add.toString())); + if (PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST) { + for (RouteSegmentResult res : result) { + String name = res.getObject().getName(); + String ref = res.getObject().getRef(); + if (name == null) { + name = ""; + } + if (ref != null) { + name += " (" + ref + ") "; + } + StringBuilder additional = new StringBuilder(); + additional.append("time = \"").append(res.getSegmentTime()).append("\" "); + additional.append("name = \"").append(name).append("\" "); +// float ms = res.getSegmentSpeed(); + float ms = res.getObject().getMaximumSpeed(); + if(ms > 0) { + additional.append("maxspeed = \"").append(ms * 3.6f).append("\" ").append(res.getObject().getHighway()).append(" "); + } + additional.append("distance = \"").append(res.getDistance()).append("\" "); + if (res.getTurnType() != null) { + additional.append("turn = \"").append(res.getTurnType()).append("\" "); + additional.append("turn_angle = \"").append(res.getTurnType().getTurnAngle()).append("\" "); + if (res.getTurnType().getLanes() != null) { + additional.append("lanes = \"").append(Arrays.toString(res.getTurnType().getLanes())).append("\" "); + } + } + additional.append("start_bearing = \"").append(res.getBearingBegin()).append("\" "); + additional.append("end_bearing = \"").append(res.getBearingEnd()).append("\" "); + additional.append("description = \"").append(res.getDescription()).append("\" "); + println(MessageFormat.format("\t", (res.getObject().getId()) + "", + res.getStartPointIndex() + "", res.getEndPointIndex() + "", additional.toString())); + } + } + println(""); + } + + + private void addTurnInfo(boolean leftside, List result) { + int prevSegment = -1; + float dist = 0; + int next = 1; + for (int i = 0; i <= result.size(); i = next) { + TurnType t = null; + next = i + 1; + if (i < result.size()) { + t = getTurnInfo(result, i, leftside); + // justify turn + if(t != null && i < result.size() - 1) { + boolean tl = TurnType.TL.equals(t.getValue()); + boolean tr = TurnType.TR.equals(t.getValue()); + if(tl || tr) { + TurnType tnext = getTurnInfo(result, i + 1, leftside); + if(tnext != null && result.get(i).getDistance() < 35) { + if(tl && TurnType.TL.equals(tnext.getValue()) ) { + next = i + 2; + t = TurnType.valueOf(TurnType.TU, false); + } else if(tr && TurnType.TR.equals(tnext.getValue()) ) { + next = i + 2; + t = TurnType.valueOf(TurnType.TU, true); + } + } + } + } + result.get(i).setTurnType(t); + } + if (t != null || i == result.size()) { + if (prevSegment >= 0) { + String turn = result.get(prevSegment).getTurnType().toString(); + if (result.get(prevSegment).getTurnType().getLanes() != null) { + turn += Arrays.toString(result.get(prevSegment).getTurnType().getLanes()); + } + result.get(prevSegment).setDescription(turn + MessageFormat.format(" and go {0,number,#.##} meters", dist)); + if(result.get(prevSegment).getTurnType().isSkipToSpeak()) { + result.get(prevSegment).setDescription("-*"+result.get(prevSegment).getDescription()); + } + } + prevSegment = i; + dist = 0; + } + if (i < result.size()) { + dist += result.get(i).getDistance(); + } + } + } + + private static final int MAX_SPEAK_PRIORITY = 5; + private int highwaySpeakPriority(String highway) { + if(highway == null || highway.endsWith("track") || highway.endsWith("services") || highway.endsWith("service") + || highway.endsWith("path")) { + return MAX_SPEAK_PRIORITY; + } + if (highway.endsWith("_link") || highway.endsWith("unclassified") || highway.endsWith("road") + || highway.endsWith("living_street") || highway.endsWith("residential") ) { + return 1; + } + return 0; + } + + + private TurnType getTurnInfo(List result, int i, boolean leftSide) { + if (i == 0) { + return TurnType.valueOf(TurnType.C, false); + } + RouteSegmentResult prev = result.get(i - 1) ; + if(prev.getObject().roundabout()) { + // already analyzed! + return null; + } + RouteSegmentResult rr = result.get(i); + if (rr.getObject().roundabout()) { + return processRoundaboutTurn(result, i, leftSide, prev, rr); + } + TurnType t = null; + if (prev != null) { + boolean noAttachedRoads = rr.getAttachedRoutes(rr.getStartPointIndex()).size() == 0; + // add description about turn + double mpi = MapUtils.degreesDiff(prev.getBearingEnd(), rr.getBearingBegin()); + if(noAttachedRoads){ + // TODO VICTOR : look at the comment inside direction route +// double begin = rr.getObject().directionRoute(rr.getStartPointIndex(), rr.getStartPointIndex() < +// rr.getEndPointIndex(), 25); +// mpi = MapUtils.degreesDiff(prev.getBearingEnd(), begin); + } + if (mpi >= TURN_DEGREE_MIN) { + if (mpi < 60) { + t = TurnType.valueOf(TurnType.TSLL, leftSide); + } else if (mpi < 120) { + t = TurnType.valueOf(TurnType.TL, leftSide); + } else if (mpi < 135 || leftSide) { + t = TurnType.valueOf(TurnType.TSHL, leftSide); + } else { + t = TurnType.valueOf(TurnType.TU, leftSide); + } + } else if (mpi < -TURN_DEGREE_MIN) { + if (mpi > -60) { + t = TurnType.valueOf(TurnType.TSLR, leftSide); + } else if (mpi > -120) { + t = TurnType.valueOf(TurnType.TR, leftSide); + } else if (mpi > -135 || !leftSide) { + t = TurnType.valueOf(TurnType.TSHR, leftSide); + } else { + t = TurnType.valueOf(TurnType.TU, leftSide); + } + } else { + t = attachKeepLeftInfoAndLanes(leftSide, prev, rr, t); + } + if (t != null) { + t.setTurnAngle((float) -mpi); + } + } + return t; + } + + + private TurnType processRoundaboutTurn(List result, int i, boolean leftSide, RouteSegmentResult prev, + RouteSegmentResult rr) { + int exit = 1; + RouteSegmentResult last = rr; + for (int j = i; j < result.size(); j++) { + RouteSegmentResult rnext = result.get(j); + last = rnext; + if (rnext.getObject().roundabout()) { + boolean plus = rnext.getStartPointIndex() < rnext.getEndPointIndex(); + int k = rnext.getStartPointIndex(); + if (j == i) { + // first exit could be immediately after roundabout enter +// k = plus ? k + 1 : k - 1; + } + while (k != rnext.getEndPointIndex()) { + int attachedRoads = rnext.getAttachedRoutes(k).size(); + if(attachedRoads > 0) { + exit++; + } + k = plus ? k + 1 : k - 1; + } + } else { + break; + } + } + // combine all roundabouts + TurnType t = TurnType.valueOf("EXIT"+exit, leftSide); + t.setTurnAngle((float) MapUtils.degreesDiff(last.getBearingBegin(), prev.getBearingEnd())) ; + return t; + } + + + private TurnType attachKeepLeftInfoAndLanes(boolean leftSide, RouteSegmentResult prevSegm, RouteSegmentResult currentSegm, TurnType t) { + // keep left/right + int[] lanes = null; + boolean kl = false; + boolean kr = false; + List attachedRoutes = currentSegm.getAttachedRoutes(currentSegm.getStartPointIndex()); + int ls = prevSegm.getObject().getLanes(); + if(ls >= 0 && prevSegm.getObject().getOneway() == 0) { + ls = (ls + 1) / 2; + } + int left = 0; + int right = 0; + boolean speak = false; + int speakPriority = Math.max(highwaySpeakPriority(prevSegm.getObject().getHighway()), highwaySpeakPriority(currentSegm.getObject().getHighway())); + if (attachedRoutes != null) { + for (RouteSegmentResult attached : attachedRoutes) { + double ex = MapUtils.degreesDiff(attached.getBearingBegin(), currentSegm.getBearingBegin()); + double mpi = Math.abs(MapUtils.degreesDiff(prevSegm.getBearingEnd(), attached.getBearingBegin())); + int rsSpeakPriority = highwaySpeakPriority(attached.getObject().getHighway()); + if (rsSpeakPriority != MAX_SPEAK_PRIORITY || speakPriority == MAX_SPEAK_PRIORITY) { + if ((ex < TURN_DEGREE_MIN || mpi < TURN_DEGREE_MIN) && ex >= 0) { + kl = true; + int lns = attached.getObject().getLanes(); + if(attached.getObject().getOneway() == 0) { + lns = (lns + 1) / 2; + } + if (lns > 0) { + right += lns; + } + speak = speak || rsSpeakPriority <= speakPriority; + } else if ((ex > -TURN_DEGREE_MIN || mpi < TURN_DEGREE_MIN) && ex <= 0) { + kr = true; + int lns = attached.getObject().getLanes(); + if(attached.getObject().getOneway() == 0) { + lns = (lns + 1) / 2; + } + if (lns > 0) { + left += lns; + } + speak = speak || rsSpeakPriority <= speakPriority; + } + } + } + } + if(kr && left == 0) { + left = 1; + } else if(kl && right == 0) { + right = 1; + } + int current = currentSegm.getObject().getLanes(); + if(currentSegm.getObject().getOneway() == 0) { + current = (current + 1) / 2; + } + if (current <= 0) { + current = 1; + } +// if(ls >= 0 /*&& current + left + right >= ls*/){ + lanes = new int[current + left + right]; + ls = current + left + right; + for(int it=0; it< ls; it++) { + if(it < left || it >= left + current) { + lanes[it] = 0; + } else { + lanes[it] = 1; + } + } + // sometimes links are + if ((current <= left + right) && (left > 1 || right > 1)) { + speak = true; + } +// } + + double devation = Math.abs(MapUtils.degreesDiff(prevSegm.getBearingEnd(), currentSegm.getBearingBegin())); + if (kl) { + t = TurnType.valueOf(devation > 5 ? TurnType.TSLL : TurnType.KL, leftSide); + t.setSkipToSpeak(!speak); + } + if (kr) { + t = TurnType.valueOf(devation > 5 ? TurnType.TSLR : TurnType.KR, leftSide); + t.setSkipToSpeak(!speak); + } + if (t != null && lanes != null) { + t.setLanes(lanes); + } + return t; + } + + + private void attachRoadSegments(RoutingContext ctx, List result, int routeInd, int pointInd, boolean plus) throws IOException { + RouteSegmentResult rr = result.get(routeInd); + RouteDataObject road = rr.getObject(); + long nextL = pointInd < road.getPointsLength() - 1 ? getPoint(road, pointInd + 1) : 0; + long prevL = pointInd > 0 ? getPoint(road, pointInd - 1) : 0; + + // attach additional roads to represent more information about the route + RouteSegmentResult previousResult = null; + + // by default make same as this road id + long previousRoadId = road.getId(); + if (pointInd == rr.getStartPointIndex() && routeInd > 0) { + previousResult = result.get(routeInd - 1); + previousRoadId = previousResult.getObject().getId(); + if (previousRoadId != road.getId()) { + if (previousResult.getStartPointIndex() < previousResult.getEndPointIndex() + && previousResult.getEndPointIndex() < previousResult.getObject().getPointsLength() - 1) { + rr.attachRoute(pointInd, new RouteSegmentResult(previousResult.getObject(), previousResult.getEndPointIndex(), + previousResult.getObject().getPointsLength() - 1)); + } else if (previousResult.getStartPointIndex() > previousResult.getEndPointIndex() + && previousResult.getEndPointIndex() > 0) { + rr.attachRoute(pointInd, new RouteSegmentResult(previousResult.getObject(), previousResult.getEndPointIndex(), 0)); + } + } + } + Iterator it; + if(rr.getPreAttachedRoutes(pointInd) != null) { + final RouteSegmentResult[] list = rr.getPreAttachedRoutes(pointInd); + it = new Iterator() { + int i = 0; + @Override + public boolean hasNext() { + return i < list.length; + } + + @Override + public RouteSegment next() { + RouteSegmentResult r = list[i++]; + return new RouteSegment(r.getObject(), r.getStartPointIndex()); + } + + @Override + public void remove() { + } + }; + } else { + RouteSegment rt = ctx.loadRouteSegment(road.getPoint31XTile(pointInd), road.getPoint31YTile(pointInd), ctx.config.memoryLimitation); + it = rt == null ? null : rt.getIterator(); + } + // try to attach all segments except with current id + while (it != null && it.hasNext()) { + RouteSegment routeSegment = it.next(); + if (routeSegment.road.getId() != road.getId() && routeSegment.road.getId() != previousRoadId) { + RouteDataObject addRoad = routeSegment.road; + checkAndInitRouteRegion(ctx, addRoad); + // TODO restrictions can be considered as well + int oneWay = ctx.getRouter().isOneWay(addRoad); + if (oneWay >= 0 && routeSegment.getSegmentStart() < addRoad.getPointsLength() - 1) { + long pointL = getPoint(addRoad, routeSegment.getSegmentStart() + 1); + if(pointL != nextL && pointL != prevL) { + // if way contains same segment (nodes) as different way (do not attach it) + rr.attachRoute(pointInd, new RouteSegmentResult(addRoad, routeSegment.getSegmentStart(), addRoad.getPointsLength() - 1)); + } + } + if (oneWay <= 0 && routeSegment.getSegmentStart() > 0) { + long pointL = getPoint(addRoad, routeSegment.getSegmentStart() - 1); + // if way contains same segment (nodes) as different way (do not attach it) + if(pointL != nextL && pointL != prevL) { + rr.attachRoute(pointInd, new RouteSegmentResult(addRoad, routeSegment.getSegmentStart(), 0)); + } + } + } + } + } + + private static void println(String logMsg) { +// log.info(logMsg); + System.out.println(logMsg); + } + + private long getPoint(RouteDataObject road, int pointInd) { + return (((long) road.getPoint31XTile(pointInd)) << 31) + (long) road.getPoint31YTile(pointInd); + } + + private static double measuredDist(int x1, int y1, int x2, int y2) { + return MapUtils.getDistance(MapUtils.get31LatitudeY(y1), MapUtils.get31LongitudeX(x1), + MapUtils.get31LatitudeY(y2), MapUtils.get31LongitudeX(x2)); + } +} diff --git a/OsmAnd-java/src/net/osmand/router/RouteSegmentResult.java b/OsmAnd-java/src/net/osmand/router/RouteSegmentResult.java new file mode 100644 index 0000000000..0086e9fcaf --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/RouteSegmentResult.java @@ -0,0 +1,169 @@ +package net.osmand.router; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.osmand.binary.RouteDataObject; +import net.osmand.data.LatLon; +import net.osmand.util.MapUtils; + + +public class RouteSegmentResult { + private final RouteDataObject object; + private int startPointIndex; + private int endPointIndex; + private List[] attachedRoutes; + private RouteSegmentResult[][] preAttachedRoutes; + private float segmentTime; + private float speed; + private float distance; + private String description = ""; + // this make not possible to make turns in between segment result for now + private TurnType turnType; + + + public RouteSegmentResult(RouteDataObject object, int startPointIndex, int endPointIndex) { + this.object = object; + this.startPointIndex = startPointIndex; + this.endPointIndex = endPointIndex; + updateCapacity(); + } + + + @SuppressWarnings("unchecked") + private void updateCapacity() { + int capacity = Math.abs(endPointIndex - startPointIndex) + 1; + List[] old = this.attachedRoutes ; + this.attachedRoutes = new List[capacity]; + if(old != null){ + System.arraycopy(old, 0, this.attachedRoutes, 0, Math.min(old.length, this.attachedRoutes.length)); + } + } + + public void attachRoute(int roadIndex, RouteSegmentResult r){ + int st = Math.abs(roadIndex - startPointIndex); + if(attachedRoutes[st] == null) { + attachedRoutes[st] = new ArrayList(); + } + attachedRoutes[st].add(r); + } + + public void copyPreattachedRoutes(RouteSegmentResult toCopy, int shift) { + if(toCopy.preAttachedRoutes != null) { + int l = toCopy.preAttachedRoutes.length - shift; + preAttachedRoutes = new RouteSegmentResult[l][]; + System.arraycopy(toCopy.preAttachedRoutes, shift, preAttachedRoutes, 0, l); + } + } + + public RouteSegmentResult[] getPreAttachedRoutes(int routeInd) { + int st = Math.abs(routeInd - startPointIndex); + if(preAttachedRoutes != null && st < preAttachedRoutes.length) { + return preAttachedRoutes[st]; + } + return null; + } + + public List getAttachedRoutes(int routeInd) { + int st = Math.abs(routeInd - startPointIndex); + List list = attachedRoutes[st]; + if(list == null) { + return Collections.emptyList(); + } + return list; + } + + public TurnType getTurnType() { + return turnType; + } + + public void setTurnType(TurnType turnType) { + this.turnType = turnType; + } + + public RouteDataObject getObject() { + return object; + } + + public float getSegmentTime() { + return segmentTime; + } + + public float getBearingBegin() { + return (float) (object.directionRoute(startPointIndex, startPointIndex < endPointIndex) / Math.PI * 180); + } + + public float getBearing(int point, boolean plus) { + return (float) (object.directionRoute(point, plus) / Math.PI * 180); + } + + public float getBearingEnd() { + return (float) (MapUtils.alignAngleDifference(object.directionRoute(endPointIndex, startPointIndex > endPointIndex) - Math.PI) / Math.PI * 180); + } + + public void setSegmentTime(float segmentTime) { + this.segmentTime = segmentTime; + } + + public LatLon getStartPoint() { + return convertPoint(object, startPointIndex); + } + + public int getStartPointIndex() { + return startPointIndex; + } + + public int getEndPointIndex() { + return endPointIndex; + } + + public LatLon getPoint(int i) { + return convertPoint(object, i); + } + + public LatLon getEndPoint() { + return convertPoint(object, endPointIndex); + } + + private LatLon convertPoint(RouteDataObject o, int ind){ + return new LatLon(MapUtils.get31LatitudeY(o.getPoint31YTile(ind)), MapUtils.get31LongitudeX(o.getPoint31XTile(ind))); + } + + public void setSegmentSpeed(float speed) { + this.speed = speed; + } + + public void setEndPointIndex(int endPointIndex) { + this.endPointIndex = endPointIndex; + updateCapacity(); + } + + public void setStartPointIndex(int startPointIndex) { + this.startPointIndex = startPointIndex; + updateCapacity(); + } + + public float getSegmentSpeed() { + return speed; + } + + public float getDistance() { + return distance; + } + + public void setDistance(float distance) { + this.distance = distance; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/router/RoutingConfiguration.java b/OsmAnd-java/src/net/osmand/router/RoutingConfiguration.java new file mode 100644 index 0000000000..794c9f3702 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/RoutingConfiguration.java @@ -0,0 +1,244 @@ +package net.osmand.router; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +import net.osmand.Collator; +import net.osmand.PlatformUtil; +import net.osmand.router.GeneralRouter.GeneralRouterProfile; +import net.osmand.util.Algorithms; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +public class RoutingConfiguration { + + public static final int DEFAULT_MEMORY_LIMIT = 30; + public Map attributes = new LinkedHashMap(); + + // 1. parameters of routing and different tweaks + // Influence on A* : f(x) + heuristicCoefficient*g(X) + public float heuristicCoefficient = 1; + + // 1.1 tile load parameters (should not affect routing) + public int ZOOM_TO_LOAD_TILES = 16; + public int memoryLimitation; + + // 1.2 Build A* graph in backward/forward direction (can affect results) + // 0 - 2 ways, 1 - direct way, -1 - reverse way + public int planRoadDirection = 0; + + // 1.3 Router specific coefficients and restrictions + public VehicleRouter router = new GeneralRouter(GeneralRouterProfile.CAR, new LinkedHashMap()); + public String routerName = ""; + + // 1.4 Used to calculate route in movement + public Double initialDirection; + + // 1.5 Recalculate distance help + public float recalculateDistance = 10000f; + + + + public static class Builder { + // Design time storage + private String defaultRouter = ""; + private Map routers = new LinkedHashMap(); + private Map attributes = new LinkedHashMap(); + + public RoutingConfiguration build(String router, int memoryLimitMB) { + return build(router, null, memoryLimitMB, new String[0]); + } + + public RoutingConfiguration build(String router, int memoryLimitMB, String[] specialization) { + return build(router, null, memoryLimitMB, specialization); + } + public RoutingConfiguration build(String router, Double direction, int memoryLimitMB, String[] specialization) { + if (!routers.containsKey(router)) { + router = defaultRouter; + } + RoutingConfiguration i = new RoutingConfiguration(); + if (routers.containsKey(router)) { + i.router = routers.get(router); + if (specialization != null) { + for (String s : specialization) { + i.router = i.router.specifyParameter(s); + } + } + i.routerName = router; + } + attributes.put("routerName", router); + i.attributes.putAll(attributes); + i.initialDirection = direction; + i.recalculateDistance = parseSilentFloat(getAttribute(i.router, "recalculateDistanceHelp"), i.recalculateDistance) ; + i.heuristicCoefficient = parseSilentFloat(getAttribute(i.router, "heuristicCoefficient"), i.heuristicCoefficient); + i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(i.router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES); + int desirable = parseSilentInt(getAttribute(i.router, "memoryLimitInMB"), 0); + if(desirable != 0) { + i.memoryLimitation = desirable * (1 << 20); + } else { + if(memoryLimitMB == 0) { + memoryLimitMB = DEFAULT_MEMORY_LIMIT; + } + i.memoryLimitation = memoryLimitMB * (1 << 20); + } + i.planRoadDirection = parseSilentInt(getAttribute(i.router, "planRoadDirection"), i.planRoadDirection); + + return i; + } + + private String getAttribute(VehicleRouter router, String propertyName) { + if (router.containsAttribute(propertyName)) { + return router.getAttribute(propertyName); + } + return attributes.get(propertyName); + } + + } + + private static int parseSilentInt(String t, int v) { + if (t == null || t.length() == 0) { + return v; + } + return Integer.parseInt(t); + } + + + private static float parseSilentFloat(String t, float v) { + if (t == null || t.length() == 0) { + return v; + } + return Float.parseFloat(t); + } + + + private static RoutingConfiguration.Builder DEFAULT; + + public static RoutingConfiguration.Builder getDefault() { + if (DEFAULT == null) { + try { + DEFAULT = parseFromInputStream(RoutingConfiguration.class.getResourceAsStream("routing.xml")); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return DEFAULT; + } + + public static RoutingConfiguration.Builder parseFromInputStream(InputStream is) throws IOException, XmlPullParserException { + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + final RoutingConfiguration.Builder config = new RoutingConfiguration.Builder(); + GeneralRouter currentRouter = null; + String previousKey = null; + String previousTag = null; + int tok; + parser.setInput(is, "UTF-8"); + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + String name = parser.getName(); + if ("osmand_routing_config".equals(name)) { + config.defaultRouter = parser.getAttributeValue("", "defaultProfile"); + } else if ("routingProfile".equals(name)) { + currentRouter = parseRoutingProfile(parser, config); + } else if ("attribute".equals(name)) { + parseAttribute(parser, config, currentRouter); + previousKey = parser.getAttributeValue("", "name"); + previousTag = name; + } else if ("specialization".equals(name)) { + parseSpecialization(parser, currentRouter, previousKey, previousTag); + } else { + previousKey = parser.getAttributeValue("", "tag") + "$" + parser.getAttributeValue("", "value"); + previousTag = name; + if (parseCurrentRule(parser, currentRouter, previousKey, name)) { + + } else { + + } + } + } + } + return config; + } + + private static boolean parseCurrentRule(XmlPullParser parser, GeneralRouter currentRouter, String key, String name) { + if ("road".equals(name)) { + currentRouter.highwayPriorities.put(key, parseSilentFloat(parser.getAttributeValue("", "priority"), 1)); + currentRouter.highwaySpeed.put(key, parseSilentFloat(parser.getAttributeValue("", "speed"), 10)); + return true; + } else if ("obstacle".equals(name)) { + float penalty = parseSilentFloat(parser.getAttributeValue("", "penalty"), 0); + currentRouter.obstacles.put(key, penalty); + float routingPenalty = parseSilentFloat(parser.getAttributeValue("", "routingPenalty"), penalty); + currentRouter.routingObstacles.put(key, routingPenalty); + return true; + } else if ("avoid".equals(name)) { + float priority = parseSilentFloat(parser.getAttributeValue("", "decreasedPriority"), 0); + if (priority == 0) { + currentRouter.avoid.put(key, priority); + } else { + currentRouter.highwayPriorities.put(key, priority); + } + return true; + } else { + return false; + } + } + + private static void parseSpecialization(XmlPullParser parser, GeneralRouter currentRouter, String previousKey, String previousTag) { + String in = parser.getAttributeValue("","input"); + if (previousKey != null) { + String k = in + ":" + previousKey; + if (parser.getAttributeValue("","penalty") != null) { + float penalty = parseSilentFloat(parser.getAttributeValue("","penalty"), 0); + currentRouter.obstacles.put(k, penalty); + float routingPenalty = parseSilentFloat(parser.getAttributeValue("","routingPenalty"), penalty ); + currentRouter.routingObstacles.put(k, routingPenalty); + } + if (parser.getAttributeValue("","priority") != null) { + currentRouter.highwayPriorities.put(k, parseSilentFloat(parser.getAttributeValue("","priority"), 0)); + } + if (parser.getAttributeValue("","speed") != null) { + currentRouter.highwaySpeed.put(k, parseSilentFloat(parser.getAttributeValue("","speed"), 0)); + } + if ("attribute".equals(previousTag)) { + currentRouter.attributes.put(k, parser.getAttributeValue("","value")); + } + if ("avoid".equals(previousTag)) { + float priority = parseSilentFloat(parser.getAttributeValue("","decreasedPriority"), 0); + if (priority == 0) { + currentRouter.avoid.put(k, priority); + } else { + currentRouter.highwayPriorities.put(k, priority); + } + } + } + } + + private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config) { + GeneralRouter currentRouter; + String currentSelectedRouter = parser.getAttributeValue("", "name"); + Map attrs = new LinkedHashMap(); + for(int i=0; i< parser.getAttributeCount(); i++) { + attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i)); + } + GeneralRouterProfile c = Algorithms.parseEnumValue(GeneralRouterProfile.values(), + parser.getAttributeValue("", "baseProfile"), GeneralRouterProfile.CAR); + currentRouter = new GeneralRouter(c, attrs); + config.routers.put(currentSelectedRouter, currentRouter); + return currentRouter; + } + + private static void parseAttribute(XmlPullParser parser, final RoutingConfiguration.Builder config, GeneralRouter currentRouter) { + if(currentRouter != null) { + currentRouter.addAttribute(parser.getAttributeValue("", "name"), + parser.getAttributeValue("", "value")); + } else { + config.attributes.put(parser.getAttributeValue("", "name"), + parser.getAttributeValue("", "value")); + } + } + +} diff --git a/OsmAnd-java/src/net/osmand/router/RoutingContext.java b/OsmAnd-java/src/net/osmand/router/RoutingContext.java new file mode 100644 index 0000000000..6331305c80 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/RoutingContext.java @@ -0,0 +1,901 @@ +package net.osmand.router; + + +import gnu.trove.iterator.TIntObjectIterator; +import gnu.trove.iterator.TLongIterator; +import gnu.trove.map.TLongObjectMap; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.map.hash.TLongObjectHashMap; +import gnu.trove.set.hash.TLongHashSet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import net.osmand.PlatformUtil; +import net.osmand.NativeLibrary; +import net.osmand.NativeLibrary.NativeRouteSearchResult; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.BinaryMapRouteReaderAdapter; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; +import net.osmand.binary.RouteDataBorderLinePoint; +import net.osmand.binary.RouteDataObject; +import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.router.BinaryRoutePlanner.RouteSegmentVisitor; +import net.osmand.util.MapUtils; + +import org.apache.commons.logging.Log; + + +public class RoutingContext { + + public static final boolean SHOW_GC_SIZE = false; + + + private final static Log log = PlatformUtil.getLog(RoutingContext.class); + public static final int OPTION_NO_LOAD = 0; + public static final int OPTION_SMART_LOAD = 1; + public static final int OPTION_IN_MEMORY_LOAD = 2; + public static boolean USE_BORDER_LINES = false; + // Final context variables + public final RoutingConfiguration config; + private final boolean useBaseMap; + public final NativeLibrary nativeLib; + public final Map> map = new LinkedHashMap>(); + public final Map reverseMap = new LinkedHashMap(); + + // 1. Initial variables + public long firstRoadId = 0; + public int firstRoadDirection = 0; + + public int startX; + public int startY; + public int targetX; + public int targetY; + + public RouteCalculationProgress calculationProgress; + public List previouslyCalculatedRoute; + public BaseRouteResult baseRouteResult; + + // 2. Routing memory cache (big objects) + TLongObjectHashMap> indexedSubregions = new TLongObjectHashMap>(); + TLongObjectHashMap> tileRoutes = new TLongObjectHashMap>(); + + RouteDataBorderLine[] borderLines = new RouteDataBorderLine[0]; + int[] borderLineCoordinates = new int[0]; + int leftBorderBoundary; + int rightBorderBoundary; + + // Needs to be a sorted array list . Another option to use hashmap but it will be more memory expensive + List subregionTiles = new ArrayList(); + + // 3. Warm object caches + ArrayList segmentsToVisitPrescripted = new ArrayList(5); + ArrayList segmentsToVisitNotForbidden = new ArrayList(5); + + + // 5. debug information (package accessor) + public TileStatistics global = new TileStatistics(); + // updated by route planner in bytes + public int memoryOverhead = 0; + + + long timeToLoad = 0; + long timeToLoadHeaders = 0; + long timeToFindInitialSegments = 0; + long timeToCalculate = 0; + + int distinctLoadedTiles = 0; + int maxLoadedTiles = 0; + int loadedPrevUnloadedTiles = 0; + int unloadedTiles = 0; + public float routingTime = 0; + public int loadedTiles = 0; + public int visitedSegments = 0; + public int relaxedSegments = 0; + // callback of processing segments + RouteSegmentVisitor visitor = null; + + + // old planner + public FinalRouteSegment finalRouteSegment; + + + + + public RoutingContext(RoutingContext cp) { + this.config = cp.config; + this.map.putAll(cp.map); + this.useBaseMap = cp.useBaseMap; + this.reverseMap.putAll(cp.reverseMap); + this.nativeLib = cp.nativeLib; + // copy local data and clear caches + for(RoutingSubregionTile tl : subregionTiles) { + if(tl.isLoaded()) { + subregionTiles.add(tl); + for (RouteSegment rs : tl.routes.valueCollection()) { + RouteSegment s = rs; + while (s != null) { + s.parentRoute = null; + s.parentSegmentEnd = 0; + s.distanceFromStart = 0; + s.distanceToEnd = 0; + s = s.next; + } + } + } + } + } + + public RoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map) { + this(config, nativeLibrary, map, false); + } + + public RoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map, boolean useBasemap) { + this.useBaseMap = useBasemap; + for (BinaryMapIndexReader mr : map) { + List rr = mr.getRoutingIndexes(); + List subregions = new ArrayList(); + for (RouteRegion r : rr) { + List subregs = useBaseMap ? r.getBaseSubregions() : + r.getSubregions(); + for (RouteSubregion rs : subregs) { + subregions.add(new RouteSubregion(rs)); + } + this.reverseMap.put(r, mr); + } + this.map.put(mr, subregions); + } + this.config = config; + this.nativeLib = nativeLibrary; + } + + + public RouteSegmentVisitor getVisitor() { + return visitor; + } + + public int getCurrentlyLoadedTiles() { + int cnt = 0; + for(RoutingSubregionTile t : this.subregionTiles){ + if(t.isLoaded()) { + cnt++; + } + } + return cnt; + } + + public int getCurrentEstimatedSize(){ + return global.size; + } + + + public void setVisitor(RouteSegmentVisitor visitor) { + this.visitor = visitor; + } + + public void setRouter(VehicleRouter router) { + config.router = router; + } + + public void setHeuristicCoefficient(float heuristicCoefficient) { + config.heuristicCoefficient = heuristicCoefficient; + } + + public VehicleRouter getRouter() { + return config.router; + } + + public boolean planRouteIn2Directions() { + return config.planRoadDirection == 0; + } + + public int getPlanRoadDirection() { + return config.planRoadDirection; + } + + public void setPlanRoadDirection(int planRoadDirection) { + config.planRoadDirection = planRoadDirection; + } + + public int roadPriorityComparator(double o1DistanceFromStart, double o1DistanceToEnd, double o2DistanceFromStart, double o2DistanceToEnd) { + return BinaryRoutePlanner.roadPriorityComparator(o1DistanceFromStart, o1DistanceToEnd, o2DistanceFromStart, o2DistanceToEnd, + config.heuristicCoefficient); + } + + public void registerRouteDataObject(RouteDataObject o ) { + if(!getRouter().acceptLine(o)){ + return; + } + for(int k = 0; k routes = tileRoutes.get(tileId); + if(routes == null){ + routes = new ArrayList(); + tileRoutes.put(tileId, routes); + } + if(!routes.contains(o)){ + routes.add(o); + } + } + } + + public void unloadAllData() { + unloadAllData(null); + } + + public void unloadAllData(RoutingContext except) { + for (RoutingSubregionTile tl : subregionTiles) { + if (tl.isLoaded()) { + if(except == null || except.searchSubregionTile(tl.subregion) < 0){ + tl.unload(); + unloadedTiles ++; + global.size -= tl.tileStatistics.size; + } + } + } + subregionTiles.clear(); + tileRoutes.clear(); + indexedSubregions.clear(); + } + + private int searchSubregionTile(RouteSubregion subregion){ + RoutingSubregionTile key = new RoutingSubregionTile(subregion); + long now = System.nanoTime(); + int ind = Collections.binarySearch(subregionTiles, key, new Comparator() { + @Override + public int compare(RoutingSubregionTile o1, RoutingSubregionTile o2) { + if(o1.subregion.left == o2.subregion.left) { + return 0; + } + return o1.subregion.left < o2.subregion.left ? 1 : -1; + } + }); + if (ind >= 0) { + for (int i = ind; i <= subregionTiles.size(); i++) { + if (i == subregionTiles.size() || subregionTiles.get(i).subregion.left > subregion.left) { + ind = -i - 1; + return ind; + } + if (subregionTiles.get(i).subregion == subregion) { + return i; + } + } + } + timeToLoadHeaders += (System.nanoTime() - now); + return ind; + } + + public void loadBorderPoints() throws IOException { + Iterator> it = reverseMap.entrySet().iterator(); + int sleft = Math.min(startX, targetX); + int sright= Math.max(startX, targetX); + int stop = Math.min(startY, targetY); + int sbottom= Math.max(startY, targetY); + // one tile of 12th zoom around (?) + int zoomAround = 10; + int distAround = 1 << (31 - zoomAround); + leftBorderBoundary = sleft - distAround; + rightBorderBoundary = sright + distAround; + SearchRequest req = BinaryMapIndexReader.buildSearchRouteBorderRequest(sleft, sright, stop, sbottom); + while(it.hasNext()) { + Entry entry = it.next(); + entry.getValue().searchBorderPoints(req, entry.getKey()); + } + TIntObjectHashMap lines = new TIntObjectHashMap(); + for(RouteDataBorderLinePoint p : req.getSearchResults()) { + if(config.router.acceptLine(p) && p.x > leftBorderBoundary && p.x < rightBorderBoundary) { + if(!lines.containsKey(p.y)) { + RouteDataBorderLine line = new RouteDataBorderLine(p.y); + lines.put(p.y, line); + RouteDataBorderLinePoint lft = new RouteDataBorderLinePoint(p.region); + lft.y = p.y; + lft.id = Long.MIN_VALUE; + lft.x = leftBorderBoundary; + line.borderPoints.add(lft); + RouteDataBorderLinePoint rht = new RouteDataBorderLinePoint(p.region); + rht.y = p.y; + rht.id = Long.MIN_VALUE; + rht.x = rightBorderBoundary; + line.borderPoints.add(rht); + } + lines.get(p.y).borderPoints.add(p); + } + } + borderLines = lines.values(new RouteDataBorderLine[lines.size()]); + Arrays.sort(borderLines); + borderLineCoordinates = new int[borderLines.length]; + for(int i=0; i 0 && borderLineCoordinates[i - 1] >> 17 == borderLineCoordinates[i] >> 17) { + throw new IllegalStateException(); + } + System.out.println("Line " + (borderLineCoordinates[i] >> 17) + + " points " + borderLines[i].borderPoints.size() /* + " " +borderLines[i].borderPoints*/); + } + + updateDistanceForBorderPoints(startX, startY, true); + updateDistanceForBorderPoints(targetX, targetY, false); + + } + + protected void updateDistanceForBorderPoints(int sX, int sy, boolean distanceToStart) { + boolean plus = borderLines.length > 0 && sy < borderLines[0].borderLine; + if(borderLines.length > 0 && !plus && sy< borderLines[borderLines.length - 1].borderLine){ + throw new IllegalStateException(); + } + // calculate min distance to start + for(int i=0; i 0){ + int prevInd = plus ? i - 1 : borderLines.length - i; + double minDist = 0; + for(RouteDataBorderLinePoint prevs : borderLines[prevInd].borderPoints){ + double d = Math.sqrt(MapUtils.squareDist31TileMetric(prevs.x, prevs.y, ps.x, ps.y)) + + (distanceToStart? prevs.distanceToStartPoint : prevs.distanceToEndPoint); + if(minDist == 0 || d < minDist) { + minDist = d; + } + } + if (minDist > 0) { +// System.out.println("Border line " + i + " exp="+res + " min="+ minDist); + res = (float) minDist; + } + } + if(distanceToStart){ + ps.distanceToStartPoint = res; + } else { + ps.distanceToEndPoint = res; + } + } + + } + } + + // returns from 0 to borderLineCoordinates.length inclusive + public int searchBorderLineIndex(int y) { + int k = Arrays.binarySearch(borderLineCoordinates, y); + if( k < 0) { + k = -(k + 1); + } + return k; + } + + public RouteSegment loadRouteSegment(int x31, int y31, int memoryLimit) { + long tileId = getRoutingTile(x31, y31, memoryLimit, OPTION_SMART_LOAD); + TLongObjectHashMap excludeDuplications = new TLongObjectHashMap(); + RouteSegment original = null; + if (tileRoutes.containsKey(tileId)) { + List routes = tileRoutes.get(tileId); + if (routes != null) { + for (RouteDataObject ro : routes) { + for (int i = 0; i < ro.pointsX.length; i++) { + if (ro.getPoint31XTile(i) == x31 && ro.getPoint31YTile(i) == y31) { + excludeDuplications.put(calcRouteId(ro, i), ro); + RouteSegment segment = new RouteSegment(ro, i); + segment.next = original; + original = segment; + } + } + } + } + } + List subregions = indexedSubregions.get(tileId); + if (subregions != null) { + for (RoutingSubregionTile rs : subregions) { + original = rs.loadRouteSegment(x31, y31, this, excludeDuplications, original); + } + } + return original; + } + + private void loadSubregionTile(final RoutingSubregionTile ts, boolean loadObjectsInMemory) { + boolean wasUnloaded = ts.isUnloaded(); + int ucount = ts.getUnloadCont(); + if (nativeLib == null) { + long now = System.nanoTime(); + try { + BinaryMapIndexReader reader = reverseMap.get(ts.subregion.routeReg); + ts.setLoadedNonNative(); + List res = reader.loadRouteIndexData(ts.subregion); +// System.out.println(ts.subregion.shiftToData + " " + res); + for(RouteDataObject ro : res){ + if(ro != null && config.router.acceptLine(ro)) { + ts.add(ro); + } + } + } catch (IOException e) { + throw new RuntimeException("Loading data exception", e); + } + + timeToLoad += (System.nanoTime() - now); + } else { + long now = System.nanoTime(); + NativeRouteSearchResult ns = nativeLib.loadRouteRegion(ts.subregion, loadObjectsInMemory); +// System.out.println(ts.subregion.shiftToData + " " + Arrays.toString(ns.objects)); + ts.setLoadedNative(ns, this); + timeToLoad += (System.nanoTime() - now); + } + loadedTiles++; + if (wasUnloaded) { + if(ucount == 1) { + loadedPrevUnloadedTiles++; + } + } else { + if(global != null) { + global.allRoutes += ts.tileStatistics.allRoutes; + global.coordinates += ts.tileStatistics.coordinates; + } + distinctLoadedTiles++; + } + global.size += ts.tileStatistics.size; + } + + private List loadTileHeaders(final int x31, final int y31) { + final int zoomToLoad = 31 - config.ZOOM_TO_LOAD_TILES; + int tileX = x31 >> zoomToLoad; + int tileY = y31 >> zoomToLoad; + + SearchRequest request = BinaryMapIndexReader.buildSearchRouteRequest(tileX << zoomToLoad, + (tileX + 1) << zoomToLoad, tileY << zoomToLoad, (tileY + 1) << zoomToLoad, null); + List collection = null; + for (Entry> r : map.entrySet()) { + // NOTE: load headers same as we do in non-native (it is not native optimized) + try { + if (r.getValue().size() > 0) { + long now = System.nanoTime(); + // int rg = r.getValue().get(0).routeReg.regionsRead; + List subregs = r.getKey().searchRouteIndexTree(request, r.getValue()); + for (RouteSubregion sr : subregs) { + int ind = searchSubregionTile(sr); + RoutingSubregionTile found; + if (ind < 0) { + found = new RoutingSubregionTile(sr); + subregionTiles.add(-(ind + 1), found); + } else { + found = subregionTiles.get(ind); + } + if (collection == null) { + collection = new ArrayList(4); + } + collection.add(found); + } + timeToLoadHeaders += (System.nanoTime() - now); + } + } catch (IOException e) { + throw new RuntimeException("Loading data exception", e); + } + } + return collection; + } + + public void loadTileData(int x31, int y31, int zoomAround, final List toFillIn) { + int t = config.ZOOM_TO_LOAD_TILES - zoomAround; + int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES)); + if(t <= 0) { + t = 1; + coordinatesShift = (1 << (31 - zoomAround)); + } else { + t = 1 << t; + } + + TLongHashSet ts = new TLongHashSet(); + long now = System.nanoTime(); + for(int i = -t; i <= t; i++) { + for(int j = -t; j <= t; j++) { + ts.add(getRoutingTile(x31 +i*coordinatesShift, y31 + j*coordinatesShift, 0, OPTION_IN_MEMORY_LOAD)); + } + } + TLongIterator it = ts.iterator(); + while(it.hasNext()){ + getAllObjects(it.next(), toFillIn); + } + timeToFindInitialSegments += (System.nanoTime() - now); + } + + @SuppressWarnings("unused") + private long getRoutingTile(int x31, int y31, int memoryLimit, int loadOptions){ +// long now = System.nanoTime(); + long xloc = x31 >> (31 - config.ZOOM_TO_LOAD_TILES); + long yloc = y31 >> (31 - config.ZOOM_TO_LOAD_TILES); + long tileId = (xloc << config.ZOOM_TO_LOAD_TILES) + yloc; + if (loadOptions != OPTION_NO_LOAD) { + if( memoryLimit == 0){ + memoryLimit = config.memoryLimitation; + } + if (getCurrentEstimatedSize() > 0.9 * memoryLimit) { + int sz1 = getCurrentEstimatedSize(); + long h1 = 0; + if (SHOW_GC_SIZE && sz1 > 0.7 * memoryLimit) { + runGCUsedMemory(); + h1 = runGCUsedMemory(); + } + int clt = getCurrentlyLoadedTiles(); + long us1 = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()); + unloadUnusedTiles(memoryLimit); + if (h1 != 0 && getCurrentlyLoadedTiles() != clt) { + int sz2 = getCurrentEstimatedSize(); + runGCUsedMemory(); + long h2 = runGCUsedMemory(); + float mb = (1 << 20); + log.warn("Unload tiles : estimated " + (sz1 - sz2) / mb + " ?= " + (h1 - h2) / mb + " actual"); + log.warn("Used after " + h2 / mb + " of " + Runtime.getRuntime().totalMemory() / mb + " max " + + maxMemory() / mb); + } else { + float mb = (1 << 20); + int sz2 = getCurrentEstimatedSize(); + log.warn("Unload tiles : occupied before " + sz1 / mb + " Mb - now " + sz2 / mb + "MB " + + memoryLimit/mb + " limit MB " + config.memoryLimitation/mb); + long us2 = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()); + log.warn("Used memory before " + us1 / mb + "after " + us1 / mb + " of max " + maxMemory() / mb); + } + } + if (!indexedSubregions.containsKey(tileId)) { + List collection = loadTileHeaders(x31, y31); + indexedSubregions.put(tileId, collection); + } + List subregions = indexedSubregions.get(tileId); + if (subregions != null) { + for (RoutingSubregionTile ts : subregions) { + if (!ts.isLoaded()) { + loadSubregionTile(ts, loadOptions == OPTION_IN_MEMORY_LOAD); + } + } + } + } + // timeToLoad += (System.nanoTime() - now); + return tileId; + } + + private long maxMemory() { + // AVIAN FIXME +// return Runtime.getRuntime().maxMemory(); + return 0; + } + + + + public boolean checkIfMemoryLimitCritical(int memoryLimit) { + return getCurrentEstimatedSize() > 0.9 * memoryLimit; + } + + public void unloadUnusedTiles(int memoryLimit) { + float desirableSize = memoryLimit * 0.7f; + List list = new ArrayList(subregionTiles.size() / 2); + int loaded = 0; + for(RoutingSubregionTile t : subregionTiles) { + if(t.isLoaded()) { + list.add(t); + loaded++; + } + } + maxLoadedTiles = Math.max(maxLoadedTiles, getCurrentlyLoadedTiles()); + Collections.sort(list, new Comparator() { + private int pow(int base, int pw) { + int r = 1; + for (int i = 0; i < pw; i++) { + r *= base; + } + return r; + } + @Override + public int compare(RoutingSubregionTile o1, RoutingSubregionTile o2) { + int v1 = (o1.access + 1) * pow(10, o1.getUnloadCont() -1); + int v2 = (o2.access + 1) * pow(10, o2.getUnloadCont() -1); + return v1 < v2 ? -1 : (v1 == v2 ? 0 : 1); + } + }); + int i = 0; + while(getCurrentEstimatedSize() >= desirableSize && (list.size() - i) > loaded / 5 && i < list.size()) { + RoutingSubregionTile unload = list.get(i); + i++; +// System.out.println("Unload " + unload); + unload.unload(); + unloadedTiles ++; + global.size -= unload.tileStatistics.size; + // tile could be cleaned from routing tiles and deleted from whole list + + } + for(RoutingSubregionTile t : subregionTiles) { + t.access /= 3; + } + } + + private void getAllObjects(long tileId, final List toFillIn) { + TLongObjectHashMap excludeDuplications = new TLongObjectHashMap(); + if (tileRoutes.containsKey(tileId)) { + List routes = tileRoutes.get(tileId); + if (routes != null) { + for (RouteDataObject ro : routes) { + if (!excludeDuplications.contains(ro.id)) { + excludeDuplications.put(ro.id, ro); + toFillIn.add(ro); + } + } + } + } + List subregions = indexedSubregions.get(tileId); + if (subregions != null) { + for (RoutingSubregionTile rs : subregions) { + rs.loadAllObjects(toFillIn, this, excludeDuplications); + } + } + } + + + + protected static long runGCUsedMemory() { + Runtime runtime = Runtime.getRuntime(); + long usedMem1 = runtime.totalMemory() - runtime.freeMemory(); + long usedMem2 = Long.MAX_VALUE; + int cnt = 4; + while (cnt-- >= 0) { + for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++i) { + // AVIAN FIXME + runtime.runFinalization(); + runtime.gc(); + Thread.yield(); + + usedMem2 = usedMem1; + usedMem1 = runtime.totalMemory() - runtime.freeMemory(); + } + } + return usedMem1; + } + + + private static long calcRouteId(RouteDataObject o, int ind) { + return (o.getId() << 10) + ind; + } + + + public static class RoutingSubregionTile { + public final RouteSubregion subregion; + // make it without get/set for fast access + public int access; + public TileStatistics tileStatistics = new TileStatistics(); + + private NativeRouteSearchResult searchResult = null; + private int isLoaded = 0; + private TLongObjectMap routes = null; + + public RoutingSubregionTile(RouteSubregion subregion) { + this.subregion = subregion; + } + + private void loadAllObjects(final List toFillIn, RoutingContext ctx, TLongObjectHashMap excludeDuplications) { + if(routes != null) { + Iterator it = routes.valueCollection().iterator(); + while(it.hasNext()){ + RouteSegment rs = it.next(); + while(rs != null){ + RouteDataObject ro = rs.road; + if (!excludeDuplications.contains(ro.id)) { + excludeDuplications.put(ro.id, ro); + toFillIn.add(ro); + } + rs = rs.next; + } + } + } else if(searchResult != null) { + RouteDataObject[] objects = searchResult.objects; + if(objects != null) { + for(RouteDataObject ro : objects) { + if (ro != null && !excludeDuplications.contains(ro.id)) { + excludeDuplications.put(ro.id, ro); + toFillIn.add(ro); + } + } + } + } + } + + private RouteSegment loadRouteSegment(int x31, int y31, RoutingContext ctx, + TLongObjectHashMap excludeDuplications, RouteSegment original) { + if(searchResult == null && routes == null) { + return original; + } + access++; + if (searchResult == null) { + long l = (((long) x31) << 31) + (long) y31; + RouteSegment segment = routes.get(l); + while (segment != null) { + RouteDataObject ro = segment.road; + RouteDataObject toCmp = excludeDuplications.get(calcRouteId(ro, segment.getSegmentStart())); + if (toCmp == null || toCmp.getPointsLength() < ro.getPointsLength()) { + excludeDuplications.put(calcRouteId(ro, segment.getSegmentStart()), ro); + RouteSegment s = new RouteSegment(ro, segment.getSegmentStart()); + s.next = original; + original = s; + } + segment = segment.next; + } + return original; + } + // Native use case + long nanoTime = System.nanoTime(); + RouteDataObject[] res = ctx.nativeLib.getDataObjects(searchResult, x31, y31); + ctx.timeToLoad += (System.nanoTime() - nanoTime); + if (res != null) { + for (RouteDataObject ro : res) { + + boolean accept = ro != null; + if (ctx != null) { + accept = ctx.getRouter().acceptLine(ro); + } + if (accept) { + for (int i = 0; i < ro.pointsX.length; i++) { + if (ro.getPoint31XTile(i) == x31 && ro.getPoint31YTile(i) == y31) { + RouteDataObject toCmp = excludeDuplications.get(calcRouteId(ro, i)); + if (toCmp == null || toCmp.getPointsLength() < ro.getPointsLength()) { + RouteSegment segment = new RouteSegment(ro, i); + segment.next = original; + original = segment; + excludeDuplications.put(calcRouteId(ro, i), ro); + } + } + } + } + } + } + return original; + } + + public boolean isLoaded() { + return isLoaded > 0; + } + + public int getUnloadCont(){ + return Math.abs(isLoaded); + } + + public boolean isUnloaded() { + return isLoaded < 0; + } + + public void unload() { + if(isLoaded == 0) { + this.isLoaded = -1; + } else { + isLoaded = -Math.abs(isLoaded); + } + if(searchResult != null) { + searchResult.deleteNativeResult(); + } + searchResult = null; + routes = null; + } + + public void setLoadedNonNative(){ + isLoaded = Math.abs(isLoaded) + 1; + routes = new TLongObjectHashMap(); + tileStatistics = new TileStatistics(); + } + + public void add(RouteDataObject ro) { + tileStatistics.addObject(ro); + for (int i = 0; i < ro.pointsX.length; i++) { + int x31 = ro.getPoint31XTile(i); + int y31 = ro.getPoint31YTile(i); + long l = (((long) x31) << 31) + (long) y31; + RouteSegment segment = new RouteSegment(ro, i); + if (!routes.containsKey(l)) { + routes.put(l, segment); + } else { + RouteSegment orig = routes.get(l); + while (orig.next != null) { + orig = orig.next; + } + orig.next = segment; + } + } + } + + public void setLoadedNative(NativeRouteSearchResult r, RoutingContext ctx) { + isLoaded = Math.abs(isLoaded) + 1; + tileStatistics = new TileStatistics(); + if (r.objects != null) { + searchResult = null; + routes = new TLongObjectHashMap(); + for (RouteDataObject ro : r.objects) { + if (ro != null && ctx.config.router.acceptLine(ro)) { + add(ro); + } + } + } else { + searchResult = r; + tileStatistics.size += 100; + } + } + } + + static int getEstimatedSize(RouteDataObject o) { + // calculate size + int sz = 0; + sz += 8 + 4; // overhead + if (o.names != null) { + sz += 12; + TIntObjectIterator it = o.names.iterator(); + while(it.hasNext()) { + it.advance(); + String vl = it.value(); + sz += 12 + vl.length(); + } + sz += 12 + o.names.size() * 25; + } + sz += 8; // id + // coordinates + sz += (8 + 4 + 4 * o.getPointsLength()) * 4; + sz += o.types == null ? 4 : (8 + 4 + 4 * o.types.length); + sz += o.restrictions == null ? 4 : (8 + 4 + 8 * o.restrictions.length); + sz += 4; + if (o.pointTypes != null) { + sz += 8 + 4 * o.pointTypes.length; + for (int i = 0; i < o.pointTypes.length; i++) { + sz += 4; + if (o.pointTypes[i] != null) { + sz += 8 + 8 * o.pointTypes[i].length; + } + } + } + // Standard overhead? + return (int) (sz * 3.5); + } + + protected static class TileStatistics { + public int size = 0; + public int allRoutes = 0; + public int coordinates = 0; + + @Override + public String toString() { + return "All routes " + allRoutes + + " size " + (size / 1024f) + " KB coordinates " + coordinates + " ratio coord " + (((float)size) / coordinates) + + " ratio routes " + (((float)size) / allRoutes); + } + + public void addObject(RouteDataObject o) { + allRoutes++; + coordinates += o.getPointsLength() * 2; + size += getEstimatedSize(o); + } + + + } + + protected static class RouteDataBorderLine implements Comparable{ + final List borderPoints = new ArrayList(); + final int borderLine; + + public RouteDataBorderLine(int borderLine) { + this.borderLine = borderLine; + } + + + @Override + public int compareTo(RouteDataBorderLine o) { + if(o.borderLine == borderLine) { + return 0; + } + return borderLine < o.borderLine? -1 : 1; + } + } + + +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/router/TestRouting.java b/OsmAnd-java/src/net/osmand/router/TestRouting.java new file mode 100644 index 0000000000..8b5d019518 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/TestRouting.java @@ -0,0 +1,332 @@ +package net.osmand.router; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import net.osmand.PlatformUtil; +import net.osmand.NativeLibrary; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.data.LatLon; +import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.router.RoutingConfiguration.Builder; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import com.ibm.icu.text.DateFormat; + +public class TestRouting { + + public static int MEMORY_TEST_LIMIT = 800; + public static boolean TEST_WO_HEURISTIC = true; + public static boolean TEST_BOTH_DIRECTION = true; + public static NativeLibrary lib = null; + public static boolean oldRouting = true; + + + public static Iterator getIterator(Iterable it){ + return it.iterator(); + } + + public static class Parameters { + public File obfDir; + public List tests = new ArrayList(); + public double startLat = 0; + public double startLon = 0; + public double endLat = 0; + public double endLon = 0; + public RoutingConfiguration.Builder configBuilder; + + public static Parameters init(String[] args) throws IOException, XmlPullParserException { + Parameters p = new Parameters(); + String routingXmlFile = null; + String obfDirectory = null; + RouteResultPreparation.PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = false; + for (String a : args) { + if (a.startsWith("-routingXmlPath=")) { + routingXmlFile = a.substring("-routingXmlPath=".length()); + } else if (a.startsWith("-verbose")) { + RouteResultPreparation.PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true; + } else if (a.startsWith("-obfDir=")) { + obfDirectory = a.substring("-obfDir=".length()); + } else if (a.startsWith("-start=")) { + String start = a.substring("-start=".length()); + String[] pt = start.split(";"); + p.startLat = Double.parseDouble(pt[0]); + p.startLon = Double.parseDouble(pt[1]); + } else if (a.startsWith("-end=")) { + String start = a.substring("-end=".length()); + String[] pt = start.split(";"); + p.endLat = Double.parseDouble(pt[0]); + p.endLon = Double.parseDouble(pt[1]); + } else if (a.startsWith("-testDir=")) { + String testDirectory = a.substring("-testDir=".length()); + for(File f : new File(testDirectory).listFiles()) { + if(f.getName().endsWith(".test.xml")){ + p.tests.add(f); + } + } + } else if(!a.startsWith("-")){ + p.tests.add(new File(a)); + } + } + + if (obfDirectory == null) { + throw new IllegalStateException("Directory with obf files not specified"); + } + p.obfDir = new File(obfDirectory); + + if (routingXmlFile == null || routingXmlFile.equals("routing.xml")) { + p.configBuilder = RoutingConfiguration.getDefault(); + } else { + p.configBuilder = RoutingConfiguration.parseFromInputStream(new FileInputStream(routingXmlFile)); + } + + return p; + } + } + + public static void main(String[] args) throws Exception { + if(args == null || args.length == 0) { + info(); + return; + } + long time = System.currentTimeMillis(); + Parameters params = Parameters.init(args); + if((params.tests.isEmpty() && params.startLat == 0) || params.obfDir == null) { + info(); + return; + } + if (!params.tests.isEmpty()) { + boolean allSuccess = runAllTests(params, lib); + if (allSuccess) { + System.out.println("All is successfull " + (System.currentTimeMillis() - time) + " ms"); + } + } + if(params.startLat != 0) { +// calculateRoute(params.obfDir.getAbsolutePath(), params.startLat, params.startLon, +// params.endLat, params.endLon); + BinaryMapIndexReader[] rs = collectFiles(params.obfDir.getAbsolutePath()); + calculateRoute(params.startLat, params.startLon, + params.endLat, params.endLon, rs); + calculateRoute(params.startLat, params.startLon, + params.endLat, params.endLon, rs); + } + + } + + + public static boolean runAllTests(Parameters params, NativeLibrary lib) throws FileNotFoundException, IOException, Exception { + BinaryMapIndexReader[] rs = collectFiles(params.obfDir.getAbsolutePath()); + + boolean allSuccess = true; + for(File f : params.tests) { + System.out.println("Before test " + f.getAbsolutePath()); + System.out.flush(); + allSuccess &= test(lib, new FileInputStream(f), rs, params.configBuilder); + } + return allSuccess; + } + + + public static void info() { + println("Run router tests is console utility to test route calculation for osmand. It is also possible to calculate one route from -start to -end."); + println("\nUsage for run tests : runTestsSuite [-routingXmlPath=PATH] [-verbose] [-obfDir=PATH] [-start=lat;lon] [-end=lat;lon] [-testDir=PATH] {individualTestPath}"); + return; + } + + + private static void println(String string) { + System.out.println(string); + } + + + public static boolean test(NativeLibrary lib, InputStream resource, BinaryMapIndexReader[] rs, RoutingConfiguration.Builder config) throws Exception { + XmlPullParser parser = PlatformUtil.newXMLPullParser(); + parser.setInput(resource, "UTF-8"); + int tok; + while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (tok == XmlPullParser.START_TAG) { + String name = parser.getName(); + if(name.equals("test")){ + testRoute(parser, config, lib, rs); + } + } + } + + return true; + } + + private static float parseFloat(XmlPullParser parser, String attr) { + String v = parser.getAttributeValue("", attr); + if(v == null || v.length() == 0){ + return 0; + } + return Float.parseFloat(v); + } + private static boolean isInOrLess(float expected, float value, float percent){ + if(equalPercent(expected, value, percent)){ + return true; + } + if(value < expected) { + System.err.println("Test could be adjusted value " + value + " is much less then expected " + expected); + return true; + } + return false; + } + + private static boolean equalPercent(float expected, float value, float percent){ + if(Math.abs(value/expected - 1) < percent / 100){ + return true; + } + return false; + } + + private static void testRoute(XmlPullParser parser, Builder config, NativeLibrary lib, BinaryMapIndexReader[] rs) throws IOException, InterruptedException { + String vehicle = parser.getAttributeValue("", "vehicle"); + int loadedTiles = (int) parseFloat(parser, "loadedTiles"); + int visitedSegments = (int) parseFloat(parser, "visitedSegments"); + int complete_time = (int) parseFloat(parser, "complete_time"); + int routing_time = (int) parseFloat(parser, "routing_time"); + int complete_distance = (int) parseFloat(parser, "complete_distance"); + float percent = parseFloat(parser, "best_percent"); + String testDescription = parser.getAttributeValue("", "description"); + if(percent == 0){ + System.err.println("\n\n!! Skipped test case '" + testDescription + "' because 'best_percent' attribute is not specified \n\n" ); + return; + } + RoutingConfiguration rconfig = config.build(vehicle, MEMORY_TEST_LIMIT); + RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(oldRouting); + RoutingContext ctx = new RoutingContext(rconfig, + lib, rs); + String skip = parser.getAttributeValue("", "skip_comment"); + if (skip != null && skip.length() > 0) { + System.err.println("\n\n!! Skipped test case '" + testDescription + "' because '" + skip + "'\n\n" ); + return; + } + System.out.println("Run test " + testDescription); + + double startLat = Double.parseDouble(parser.getAttributeValue("", "start_lat")); + double startLon = Double.parseDouble(parser.getAttributeValue("", "start_lon")); + double endLat = Double.parseDouble(parser.getAttributeValue("", "target_lat")); + double endLon = Double.parseDouble(parser.getAttributeValue("", "target_lon")); + LatLon start = new LatLon(startLat, startLon); + LatLon end = new LatLon(endLat, endLon); + List route = router.searchRoute(ctx, start, end, null, false); + final float calcRoutingTime = ctx.routingTime; + float completeTime = 0; + float completeDistance = 0; + for (int i = 0; i < route.size(); i++) { + completeTime += route.get(i).getSegmentTime(); + completeDistance += route.get(i).getDistance(); + } + if(complete_time > 0 && !isInOrLess(complete_time, completeTime, percent)) { + throw new IllegalArgumentException(MessageFormat.format("Complete time (expected) {0} != {1} (original) : {2}", complete_time, completeTime, testDescription)); + } + if(complete_distance > 0 && !isInOrLess(complete_distance, completeDistance, percent)) { + throw new IllegalArgumentException(MessageFormat.format("Complete distance (expected) {0} != {1} (original) : {2}", complete_distance, completeDistance, testDescription)); + } + if(routing_time > 0 && !isInOrLess(routing_time, calcRoutingTime, percent)) { + throw new IllegalArgumentException(MessageFormat.format("Complete routing time (expected) {0} != {1} (original) : {2}", routing_time, calcRoutingTime, testDescription)); + } + + if (visitedSegments > 0 && !isInOrLess(visitedSegments, ctx.visitedSegments, percent)) { + throw new IllegalArgumentException(MessageFormat.format("Visited segments (expected) {0} != {1} (original) : {2}", visitedSegments, + ctx.visitedSegments, testDescription)); + } + if (loadedTiles > 0 && !isInOrLess(loadedTiles, ctx.loadedTiles, percent)) { + throw new IllegalArgumentException(MessageFormat.format("Loaded tiles (expected) {0} != {1} (original) : {2}", loadedTiles, + ctx.loadedTiles, testDescription)); + } + + if(TEST_BOTH_DIRECTION){ + rconfig.planRoadDirection = -1; + runTestSpecialTest(lib, rs, rconfig, router, start, end, calcRoutingTime, "Calculated routing time in both direction {0} != {1} time in -1 direction"); + + rconfig.planRoadDirection = 1; + runTestSpecialTest(lib, rs, rconfig, router, start, end, calcRoutingTime, "Calculated routing time in both direction {0} != {1} time in 1 direction"); + + } + + if(TEST_WO_HEURISTIC) { + rconfig.planRoadDirection = 0; + rconfig.heuristicCoefficient = 0.5f; + runTestSpecialTest(lib, rs, rconfig, router, start, end, calcRoutingTime, + "Calculated routing time with heuristic 1 {0} != {1} with heuristic 0.5"); + } + + } + + + private static void runTestSpecialTest(NativeLibrary lib, BinaryMapIndexReader[] rs, RoutingConfiguration rconfig, RoutePlannerFrontEnd router, + LatLon start, LatLon end, final float calcRoutingTime, String msg) throws IOException, InterruptedException { + RoutingContext ctx; + ctx = new RoutingContext(rconfig, lib, rs); + router.searchRoute(ctx, start, end, null, false); + FinalRouteSegment frs = ctx.finalRouteSegment; + if(frs == null || !equalPercent(calcRoutingTime, frs.distanceFromStart, 0.5f)){ + throw new IllegalArgumentException(MessageFormat.format(msg, calcRoutingTime+"",frs == null?"0":frs.distanceFromStart+"")); + } + } + + + + public static void calculateRoute(String folderWithObf, + double startLat, double startLon, double endLat, double endLon) throws IOException, InterruptedException { + BinaryMapIndexReader[] rs = collectFiles(folderWithObf); + RouteResultPreparation.PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = false; + calculateRoute(startLat, startLon, endLat, endLon, rs); + calculateRoute(startLat, startLon, endLat, endLon, rs); + } + + private static BinaryMapIndexReader[] collectFiles(String folderWithObf) throws FileNotFoundException, IOException { + List files = new ArrayList(); + for (File f : new File(folderWithObf).listFiles()) { + if (f.getName().endsWith(".obf")) { + files.add(f); + } + } + BinaryMapIndexReader[] rs = new BinaryMapIndexReader[files.size()]; + int it = 0; + for (File f : files) { + RandomAccessFile raf = new RandomAccessFile(f.getAbsolutePath(), "r"); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println(f.getName()); + rs[it++] = new BinaryMapIndexReader(raf); + } + return rs; + } + + + private static void calculateRoute(double startLat, double startLon, double endLat, double endLon, BinaryMapIndexReader[] rs) + throws IOException, InterruptedException { + long ts = System.currentTimeMillis(); + Builder config = RoutingConfiguration.getDefault(); + RoutingConfiguration rconfig = config.build("car", MEMORY_TEST_LIMIT); + RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(oldRouting); + RoutingContext ctx = new RoutingContext(rconfig, lib, rs); + RouteSegment startSegment = router.findRouteSegment(startLat, startLon, ctx); + RouteSegment endSegment = router.findRouteSegment(endLat, endLon, ctx); + if(startSegment == null){ + throw new IllegalArgumentException("Start segment is not found "); + } + if(endSegment == null){ + throw new IllegalArgumentException("End segment is not found "); + } + List route = router.searchRoute(ctx, + new LatLon(startLat, startLon), new LatLon(endLat, endLon), null, false); + System.out.println("Route is " + route.size() + " segments " + (System.currentTimeMillis() - ts) + " ms "); + } + +} diff --git a/OsmAnd-java/src/net/osmand/router/TurnType.java b/OsmAnd-java/src/net/osmand/router/TurnType.java new file mode 100644 index 0000000000..42b8b05674 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/TurnType.java @@ -0,0 +1,136 @@ +package net.osmand.router; + +public class TurnType { + public static final String C = "C"; // continue (go straight) //$NON-NLS-1$ + public static final String TL = "TL"; // turn left //$NON-NLS-1$ + public static final String TSLL = "TSLL"; // turn slightly left //$NON-NLS-1$ + public static final String TSHL = "TSHL"; // turn sharply left //$NON-NLS-1$ + public static final String TR = "TR"; // turn right //$NON-NLS-1$ + public static final String TSLR = "TSLR"; // turn slightly right //$NON-NLS-1$ + public static final String TSHR = "TSHR"; // turn sharply right //$NON-NLS-1$ + public static final String KL = "KL"; // keep left //$NON-NLS-1$ + public static final String KR = "KR"; // keep right//$NON-NLS-1$ + public static final String TU = "TU"; // U-turn //$NON-NLS-1$ + public static final String TRU = "TRU"; // Right U-turn //$NON-NLS-1$ + public static String[] predefinedTypes = new String[] { C, KL, KR, TL, TSLL, TSHL, TR, TSLR, TSHR, TU, TRU }; + + public static TurnType valueOf(String s, boolean leftSide) { + for (String v : predefinedTypes) { + if (v.equals(s)) { + if (leftSide && TU.equals(v)) { + v = TRU; + } + return new TurnType(v); + } + } + if (s != null && s.startsWith("EXIT")) { //$NON-NLS-1$ + return getExitTurn(Integer.parseInt(s.substring(4)), 0, leftSide); + } + return null; + } + + private final String value; + private int exitOut; + private boolean isLeftSide; + // calculated clockwise head rotation if previous direction to NORTH + private float turnAngle; + private boolean skipToSpeak; + private int[] lanes; + + private static TurnType getExitTurn(int out, float angle, boolean leftSide) { + TurnType r = new TurnType("EXIT", out, leftSide); //$NON-NLS-1$ + r.setTurnAngle(angle); + return r; + } + + private TurnType(String value, int exitOut, boolean leftSide) { + this.value = value; + this.exitOut = exitOut; + this.isLeftSide = leftSide; + } + + // calculated Clockwise head rotation if previous direction to NORTH + public float getTurnAngle() { + return turnAngle; + } + + public boolean isLeftSide() { + return isLeftSide; + } + + public void setTurnAngle(float turnAngle) { + this.turnAngle = turnAngle; + } + + private TurnType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public int getExitOut() { + return exitOut; + } + + public boolean isRoundAbout() { + return value.equals("EXIT"); //$NON-NLS-1$ + } + + // lanes encoded as array of int + // last bit is 1, 0 (should we take this lane) + // first bits 0 - left, 1 - straight, 2 - right + public void setLanes(int[] lanes) { + this.lanes = lanes; + } + + public int[] getLanes() { + return lanes; + } + + public boolean keepLeft() { + return value.equals(KL); + } + + public boolean keepRight() { + return value.equals(KR); + } + + public boolean isSkipToSpeak() { + return skipToSpeak; + } + public void setSkipToSpeak(boolean skipToSpeak) { + this.skipToSpeak = skipToSpeak; + } + + @Override + public String toString() { + if(isRoundAbout()){ + return "Take " + getExitOut() + " exit"; + } else if(value.equals(C)) { + return "Go ahead"; + } else if(value.equals(TSLL)) { + return "Turn slightly left"; + } else if(value.equals(TL)) { + return "Turn left"; + } else if(value.equals(TSHL)) { + return "Turn sharply left"; + } else if(value.equals(TSLR)) { + return "Turn slightly right"; + } else if(value.equals(TR)) { + return "Turn right"; + } else if(value.equals(TSHR)) { + return "Turn sharply right"; + } else if(value.equals(TU)) { + return "Make uturn"; + } else if(value.equals(TRU)) { + return "Make uturn"; + } else if(value.equals(KL)) { + return "Keep left"; + } else if(value.equals(KR)) { + return "Keep right"; + } + return super.toString(); + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/router/VehicleRouter.java b/OsmAnd-java/src/net/osmand/router/VehicleRouter.java new file mode 100644 index 0000000000..d23cdd244f --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/VehicleRouter.java @@ -0,0 +1,68 @@ +package net.osmand.router; + +import net.osmand.binary.RouteDataObject; +import net.osmand.router.BinaryRoutePlanner.RouteSegment; + +public abstract class VehicleRouter { + + /** + * Accepts line to use it for routing + * + * @param way + * @return + */ + public abstract boolean acceptLine(RouteDataObject way); + + public abstract boolean restrictionsAware(); + + public abstract int isOneWay(RouteDataObject road); + + public abstract boolean containsAttribute(String attribute); + + public abstract String getAttribute(String attribute); + + + /** + * return delay in seconds + */ + public float defineObstacle(RouteDataObject road, int point) { + // no obstacles + return 0; + } + + public float defineRoutingObstacle(RouteDataObject road, int point) { + // no obstacles + return 0; + } + + /** + * return speed in m/s for vehicle for specified road + */ + public abstract float defineSpeed(RouteDataObject road); + + /** + * define priority to multiply the speed for g(x) A* + */ + public abstract float defineSpeedPriority(RouteDataObject road); + + /** + * Used for A* routing to calculate g(x) + * + * @return minimal speed at road in m/s + */ + public abstract float getMinDefaultSpeed(); + + /** + * Used for A* routing to predict h(x) : it should be great any g(x) + * + * @return maximum speed to calculate shortest distance + */ + public abstract float getMaxDefaultSpeed(); + + public abstract VehicleRouter specifyParameter(String tag); + + /** + * Calculate turn time + */ + public abstract double calculateTurnTime(RouteSegment segment, int segmentEnd, RouteSegment prev, int prevSegmentEnd) ; +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/router/routing.xml b/OsmAnd-java/src/net/osmand/router/routing.xml new file mode 100644 index 0000000000..6ab97b6161 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/router/routing.xml @@ -0,0 +1,651 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd-java/src/net/osmand/util/Algorithms.java b/OsmAnd-java/src/net/osmand/util/Algorithms.java new file mode 100644 index 0000000000..bc4ed5b77b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/util/Algorithms.java @@ -0,0 +1,323 @@ +package net.osmand.util; + + +import java.io.Closeable; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + +import net.osmand.PlatformUtil; + +import org.apache.commons.logging.Log; + + +/** + * Basic algorithms that are not in jdk + */ +public class Algorithms { + private static final int BUFFER_SIZE = 1024; + private static final Log log = PlatformUtil.getLog(Algorithms.class); + + public static boolean isEmpty(String s){ + return s == null || s.length() == 0; + } + + /** + * Determine whether a file is a ZIP File. + */ + public static boolean isZipFile(File file) throws IOException { + if (file.isDirectory()) { + return false; + } + if (!file.canRead()) { + throw new IOException("Cannot read file " + file.getAbsolutePath()); + } + if (file.length() < 4) { + return false; + } + FileInputStream in = new FileInputStream(file); + int test = readInt(in); + in.close(); + return test == 0x504b0304; + } + + private static final int readInt(InputStream in) throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + int ch3 = in.read(); + int ch4 = in.read(); + if ((ch1 | ch2 | ch3 | ch4) < 0) + throw new EOFException(); + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); + } + + public static String capitalizeFirstLetterAndLowercase(String s) { + if (s != null && s.length() > 1) { + // not very efficient algorithm + return Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase(); + } else { + return s; + } + } + + + public static boolean objectEquals(Object a, Object b){ + if(a == null){ + return b == null; + } else { + return a.equals(b); + } + } + + public static int extractFirstIntegerNumber(String s) { + int i = 0; + for (int k = 0; k < s.length(); k++) { + if (Character.isDigit(s.charAt(k))) { + i = i * 10 + (s.charAt(k) - '0'); + } else { + break; + } + } + return i; + } + + public static String extractIntegerSuffix(String s) { + int k = 0; + for (; k < s.length(); k++) { + if (!Character.isDigit(s.charAt(k))) { + return s.substring(k); + } + } + return ""; + } + + + public static void streamCopy(InputStream in, OutputStream out) throws IOException{ + byte[] b = new byte[BUFFER_SIZE]; + int read; + while ((read = in.read(b)) != -1) { + out.write(b, 0, read); + } + } + + public static void oneByteStreamCopy(InputStream in, OutputStream out) throws IOException{ + int read; + while ((read = in.read()) != -1) { + out.write(read); + } + } + + public static void closeStream(Closeable stream){ + try { + if(stream != null){ + stream.close(); + } + } catch(IOException e){ + log.warn("Closing stream warn", e); //$NON-NLS-1$ + } + } + + public static void updateAllExistingImgTilesToOsmandFormat(File f){ + if(f.isDirectory()){ + for(File c : f.listFiles()){ + updateAllExistingImgTilesToOsmandFormat(c); + } + } else if(f.getName().endsWith(".png") || f.getName().endsWith(".jpg")){ //$NON-NLS-1$ //$NON-NLS-2$ + f.renameTo(new File(f.getAbsolutePath() + ".tile")); //$NON-NLS-1$ + } else if(f.getName().endsWith(".andnav2")) { //$NON-NLS-1$ + f.renameTo(new File(f.getAbsolutePath().substring(0, f.getAbsolutePath().length() - ".andnav2".length()) + ".tile")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + } + + public static boolean removeAllFiles(File f) { + if (f == null) { + return false; + } + if (f.isDirectory()) { + File[] fs = f.listFiles(); + if(fs != null) { + for (File c : fs) { + removeAllFiles(c); + } + } + return f.delete(); + } else { + return f.delete(); + } + } + + + public static long parseLongFromBytes(byte[] bytes, int offset) { + long o= 0xff & bytes[offset + 7]; + o = o << 8 | (0xff & bytes[offset + 6]); + o = o << 8 | (0xff & bytes[offset + 5]); + o = o << 8 | (0xff & bytes[offset + 4]); + o = o << 8 | (0xff & bytes[offset + 3]); + o = o << 8 | (0xff & bytes[offset + 2]); + o = o << 8 | (0xff & bytes[offset + 1]); + o = o << 8 | (0xff & bytes[offset + 0]); + return o; + } + + + + public static void putLongToBytes(byte[] bytes, int offset, long l){ + bytes[offset] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 1] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 2] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 3] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 4] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 5] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 6] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 7] = (byte) (l & 0xff); + } + + + public static int parseIntFromBytes(byte[] bytes, int offset) { + int o = (0xff & bytes[offset + 3]) << 24; + o |= (0xff & bytes[offset + 2]) << 16; + o |= (0xff & bytes[offset + 1]) << 8; + o |= (0xff & bytes[offset + 0]); + return o; + } + + public static void putIntToBytes(byte[] bytes, int offset, int l){ + bytes[offset] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 1] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 2] = (byte) (l & 0xff); + l >>= 8; + bytes[offset + 3] = (byte) (l & 0xff); + } + + + public static void writeLongInt(OutputStream stream, long l) throws IOException { + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + l >>= 8; + stream.write((int) (l & 0xff)); + } + + public static void writeInt(OutputStream stream, int l) throws IOException { + stream.write(l & 0xff); + l >>= 8; + stream.write(l & 0xff); + l >>= 8; + stream.write(l & 0xff); + l >>= 8; + stream.write(l & 0xff); + } + + + public static void writeSmallInt(OutputStream stream, int l) throws IOException { + stream.write(l & 0xff); + l >>= 8; + stream.write(l & 0xff); + l >>= 8; + } + + public static int parseSmallIntFromBytes(byte[] bytes, int offset) { + int s = (0xff & bytes[offset + 1]) << 8; + s |= (0xff & bytes[offset + 0]); + return s; + } + + public static void putSmallIntBytes(byte[] bytes, int offset, int s){ + bytes[offset] = (byte) (s & 0xff); + s >>= 8; + bytes[offset + 1] = (byte) (s & 0xff); + s >>= 8; + } + + public static boolean containsDigit(String name) { + for (int i = 0; i < name.length(); i++) { + if (Character.isDigit(name.charAt(i))) { + return true; + } + } + return false; + } + + + public static String formatDuration(int seconds) { + String sec; + if (seconds % 60 < 10) { + sec = "0" + (seconds % 60); + } else { + sec = (seconds % 60) + ""; + } + int minutes = seconds / 60; + if (minutes < 60) { + return minutes + ":" + sec; + } else { + String min; + if (minutes % 60 < 10) { + min = "0" + (minutes % 60); + } else { + min = (minutes % 60) + ""; + } + int hours = minutes / 60; + return hours + ":" + min + ":" + sec; + } + } + + public static > T parseEnumValue(T[] cl, String val, T defaultValue){ + for(int i = 0; i< cl.length; i++) { + if(cl[i].name().equalsIgnoreCase(val)) { + return cl[i]; + } + } + return defaultValue; + } + + private static java.text.DateFormat dateFormat; + private static java.text.DateFormat dateTimeFormat; + public static String formatDate(long t) { + return getDateFormat().format(new Date(t)); + } + + public static DateFormat getDateFormat() { + if(dateFormat == null) { + dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); + } + return dateFormat; + } + + public static DateFormat getDateTimeFormat() { + if (dateTimeFormat == null) { + dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault()); + } + return dateTimeFormat; + } + + public static String formatDateTime(long t) { + return getDateTimeFormat().format(new Date(t)); + } + +} diff --git a/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java b/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java new file mode 100644 index 0000000000..802c0ee19a --- /dev/null +++ b/OsmAnd-java/src/net/osmand/util/MapAlgorithms.java @@ -0,0 +1,293 @@ +package net.osmand.util; + +import gnu.trove.list.TLongList; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.osmand.data.LatLon; + +public class MapAlgorithms { + + public static boolean isClockwiseWay(TLongList c) { + if (c.size() == 0) { + return true; + } + + // calculate middle Y + long mask = 0xffffffffl; + long middleY = 0; + for (int i = 0; i < c.size(); i++) { + middleY = middleY + (long)(c.get(i) & mask); + } + middleY = middleY /(long) c.size(); + + double clockwiseSum = 0; + + boolean firstDirectionUp = false; + int previousX = Integer.MIN_VALUE; + int firstX = Integer.MIN_VALUE; + + int prevX = (int) (c.get(0) >> 32); + int prevY = (int) (c.get(0) & mask); + + for (int i = 1; i < c.size(); i++) { + int x = (int) (c.get(i) >> 32); + int y = (int) (c.get(i) & mask); + int rX = ray_intersect_x(prevX, prevY, x, y, (int) middleY); + if (rX != Integer.MIN_VALUE) { + boolean skipSameSide = (y <= middleY) == (prevY <= middleY); + if (skipSameSide) { + continue; + } + boolean directionUp = prevY >= middleY; + if (firstX == Integer.MIN_VALUE) { + firstDirectionUp = directionUp; + firstX = rX; + } else { + boolean clockwise = (!directionUp) == (previousX < rX); + if (clockwise) { + clockwiseSum += Math.abs(previousX - rX); + } else { + clockwiseSum -= Math.abs(previousX - rX); + } + } + previousX = rX; + } + prevX = x; + prevY = y; + } + if (firstX != Integer.MIN_VALUE) { + boolean clockwise = (!firstDirectionUp) == (previousX < firstX); + if (clockwise) { + clockwiseSum += Math.abs(previousX - firstX); + } else { + clockwiseSum -= Math.abs(previousX - firstX); + } + } + + return clockwiseSum >= 0; + } + + + public static int ray_intersect_x(int prevX, int prevY, int x, int y, int middleY) { + // prev node above line + // x,y node below line + if (prevY > y) { + int tx = x; + int ty = y; + x = prevX; + y = prevY; + prevX = tx; + prevY = ty; + } + if (y == middleY || prevY == middleY) { + middleY -= 1; + } + if (prevY > middleY || y < middleY) { + return Integer.MIN_VALUE; + } else { + if (y == prevY) { + // the node on the boundary !!! + return x; + } + // that tested on all cases (left/right) + double rx = x + ((double) middleY - y) * ((double) x - prevX) / (((double) y - prevY)); + return (int) rx; + } + } + + + + private static long combine2Points(int x, int y) { + return (((long) x ) <<32) | ((long)y ); + } + /** + * outx,outy are the coordinates out of the box + * inx,iny are the coordinates from the box (NOT IMPORTANT in/out, just one should be in second out) + * @return -1 if there is no instersection or x<<32 | y + */ + public static long calculateIntersection(int inx, int iny, int outx, int outy, int leftX, int rightX, int bottomY, int topY) { + int by = -1; + int bx = -1; + // firstly try to search if the line goes in + if (outy < topY && iny >= topY) { + int tx = (int) (outx + ((double) (inx - outx) * (topY - outy)) / (iny - outy)); + if (leftX <= tx && tx <= rightX) { + bx = tx; + by = topY; + return combine2Points(bx, by); + } + } + if (outy > bottomY && iny <= bottomY) { + int tx = (int) (outx + ((double) (inx - outx) * (outy - bottomY)) / (outy - iny)); + if (leftX <= tx && tx <= rightX) { + bx = tx; + by = bottomY; + return combine2Points(bx, by); + } + } + if (outx < leftX && inx >= leftX) { + int ty = (int) (outy + ((double) (iny - outy) * (leftX - outx)) / (inx - outx)); + if (ty >= topY && ty <= bottomY) { + by = ty; + bx = leftX; + return combine2Points(bx, by); + } + + } + if (outx > rightX && inx <= rightX) { + int ty = (int) (outy + ((double) (iny - outy) * (outx - rightX)) / (outx - inx)); + if (ty >= topY && ty <= bottomY) { + by = ty; + bx = rightX; + return combine2Points(bx, by); + } + + } + + // try to search if point goes out + if (outy > topY && iny <= topY) { + int tx = (int) (outx + ((double) (inx - outx) * (topY - outy)) / (iny - outy)); + if (leftX <= tx && tx <= rightX) { + bx = tx; + by = topY; + return combine2Points(bx, by); + } + } + if (outy < bottomY && iny >= bottomY) { + int tx = (int) (outx + ((double) (inx - outx) * (outy - bottomY)) / (outy - iny)); + if (leftX <= tx && tx <= rightX) { + bx = tx; + by = bottomY; + return combine2Points(bx, by); + } + } + if (outx > leftX && inx <= leftX) { + int ty = (int) (outy + ((double) (iny - outy) * (leftX - outx)) / (inx - outx)); + if (ty >= topY && ty <= bottomY) { + by = ty; + bx = leftX; + return combine2Points(bx, by); + } + + } + if (outx < rightX && inx >= rightX) { + int ty = (int) (outy + ((double) (iny - outy) * (outx - rightX)) / (outx - inx)); + if (ty >= topY && ty <= bottomY) { + by = ty; + bx = rightX; + return combine2Points(bx, by); + } + + } + + if (outx == rightX || outx == leftX || outy == topY || outy == bottomY) { + bx = outx; + by = outy; + //return (((long) bx) << 32) | ((long) by); + } + return -1l; + } + + /** + * return true if the line segment [a,b] intersects [c,d] + * @param a point 1 + * @param b point 2 + * @param c point 3 + * @param d point 4 + * @return true if the line segment [a,b] intersects [c,d] + */ + + public static boolean linesIntersect(LatLon a, LatLon b, LatLon c, LatLon d){ + + return linesIntersect( + a.getLatitude(), a.getLongitude(), + b.getLatitude(), b.getLongitude(), + c.getLatitude(), c.getLongitude(), + d.getLatitude(), d.getLongitude()); + + } + + /** + * Return true if two line segments intersect inside the segment + * + * source: http://www.java-gaming.org/index.php?topic=22590.0 + * @param x1 line 1 point 1 latitude + * @param y1 line 1 point 1 longitude + * @param x2 line 1 point 2 latitude + * @param y2 line 1 point 2 longitude + * @param x3 line 2 point 1 latitude + * @param y3 line 2 point 1 longitude + * @param x4 line 2 point 2 latitude + * @param y4 line 2 point 2 longitude + * @return + */ + + public static boolean linesIntersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){ + + // Return false if either of the lines have zero length + if (x1 == x2 && y1 == y2 || + x3 == x4 && y3 == y4){ + return false; + } + + // Fastest method, based on Franklin Antonio's "Faster Line Segment Intersection" topic "in Graphics Gems III" book (http://www.graphicsgems.org/) + + double ax = x2-x1; + double ay = y2-y1; + double bx = x3-x4; + double by = y3-y4; + double cx = x1-x3; + double cy = y1-y3; + + + double alphaNumerator = by*cx - bx*cy; + double commonDenominator = ay*bx - ax*by; + if (commonDenominator > 0){ + if (alphaNumerator < 0 || alphaNumerator > commonDenominator){ + return false; + } + }else if (commonDenominator < 0){ + if (alphaNumerator > 0 || alphaNumerator < commonDenominator){ + return false; + } + } + + double betaNumerator = ax*cy - ay*cx; + if (commonDenominator > 0){ + if (betaNumerator < 0 || betaNumerator > commonDenominator){ + return false; + } + }else if (commonDenominator < 0){ + if (betaNumerator > 0 || betaNumerator < commonDenominator){ + return false; + } + } + + if (commonDenominator == 0){ + // This code wasn't in Franklin Antonio's method. It was added by Keith Woodward. + // The lines are parallel. + // Check if they're collinear. + double y3LessY1 = y3-y1; + double collinearityTestForP3 = x1*(y2-y3) + x2*(y3LessY1) + x3*(y1-y2); // see http://mathworld.wolfram.com/Collinear.html + // If p3 is collinear with p1 and p2 then p4 will also be collinear, since p1-p2 is parallel with p3-p4 + + if (collinearityTestForP3 == 0){ + // The lines are collinear. Now check if they overlap. + if (x1 >= x3 && x1 <= x4 || x1 <= x3 && x1 >= x4 || + x2 >= x3 && x2 <= x4 || x2 <= x3 && x2 >= x4 || + x3 >= x1 && x3 <= x2 || x3 <= x1 && x3 >= x2){ + if (y1 >= y3 && y1 <= y4 || y1 <= y3 && y1 >= y4 || + y2 >= y3 && y2 <= y4 || y2 <= y3 && y2 >= y4 || + y3 >= y1 && y3 <= y2 || y3 <= y1 && y3 >= y2){ + return true; + } + } + } + return false; + } + return true; + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/net/osmand/util/MapUtils.java b/OsmAnd-java/src/net/osmand/util/MapUtils.java new file mode 100644 index 0000000000..8a0224f927 --- /dev/null +++ b/OsmAnd-java/src/net/osmand/util/MapUtils.java @@ -0,0 +1,438 @@ +package net.osmand.util; + + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import net.osmand.data.LatLon; +import net.osmand.data.MapObject; + + +/** + * This utility class includes : + * 1. distance algorithms + * 2. finding center for array of nodes + * 3. tile evaluation algorithms + * + * + */ +public class MapUtils { + + private static final String BASE_SHORT_OSM_URL = "http://osm.org/go/"; + + /** + * This array is a lookup table that translates 6-bit positive integer + * index values into their "Base64 Alphabet" equivalents as specified + * in Table 1 of RFC 2045. + */ + private static final char intToBase64[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '@' + }; + + public static double getDistance(LatLon l, double latitude, double longitude){ + return getDistance(l.getLatitude(), l.getLongitude(), latitude, longitude); + } + + private static double scalarMultiplication(double xA, double yA, double xB, double yB, double xC, double yC) { + // Scalar multiplication between (AB, AC) + double multiple = (xB - xA) * (xC - xA) + (yB- yA) * (yC -yA); + return multiple; + } + + public static double getOrthogonalDistance(double lat, double lon, double fromLat, double fromLon, double toLat, double toLon) { + return getDistance(getProjection(lat, lon, fromLat, fromLon, toLat, toLon), lat, lon); + } + + public static LatLon getProjection(double lat, double lon, double fromLat, double fromLon, double toLat, double toLon) { + // not very accurate computation on sphere but for distances < 1000m it is ok + double mDist = (fromLat - toLat) * (fromLat - toLat) + (fromLon - toLon) * (fromLon - toLon); + double projection = scalarMultiplication(fromLat, fromLon, toLat, toLon, lat, lon); + double prlat; + double prlon; + if (projection < 0) { + prlat = fromLat; + prlon = fromLon; + } else if (projection >= mDist) { + prlat = toLat; + prlon = toLon; + } else { + prlat = fromLat + (toLat - fromLat) * (projection / mDist); + prlon = fromLon + (toLon - fromLon) * (projection / mDist); + } + return new LatLon(prlat, prlon); + } + + private static double toRadians(double angdeg) { +// return Math.toRadians(angdeg); + return angdeg / 180.0 * Math.PI; + } + + /** + * Gets distance in meters + */ + public static double getDistance(double lat1, double lon1, double lat2, double lon2){ + double R = 6371; // km + double dLat = toRadians(lat2-lat1); + double dLon = toRadians(lon2-lon1); + double a = Math.sin(dLat/2) * Math.sin(dLat/2) + + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * + Math.sin(dLon/2) * Math.sin(dLon/2); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); + return R * c * 1000; + } + + + /** + * Gets distance in meters + */ + public static double getDistance(LatLon l1, LatLon l2){ + return getDistance(l1.getLatitude(), l1.getLongitude(), l2.getLatitude(), l2.getLongitude()); + } + + public static double checkLongitude(double longitude) { + while (longitude < -180 || longitude > 180) { + if (longitude < 0) { + longitude += 360; + } else { + longitude -= 360; + } + } + return longitude; + } + + public static double checkLatitude(double latitude) { + while (latitude < -90 || latitude > 90) { + if (latitude < 0) { + latitude += 180; + } else { + latitude -= 180; + } + } + if(latitude < -85.0511) { + return -85.0511; + } else if(latitude > 85.0511){ + return 85.0511; + } + return latitude; + } + + public static int get31TileNumberX(double longitude){ + longitude = checkLongitude(longitude); + long l = 1l << 31; + return (int)((longitude + 180d)/360d * l); + } + public static int get31TileNumberY( double latitude){ + latitude = checkLatitude(latitude); + double eval = Math.log( Math.tan(toRadians(latitude)) + 1/Math.cos(toRadians(latitude)) ); + long l = 1l << 31; + if(eval > Math.PI){ + eval = Math.PI; + } + return (int) ((1 - eval / Math.PI) / 2 * l); + } + + public static double get31LongitudeX(int tileX){ + return MapUtils.getLongitudeFromTile(21, tileX /1024f); + } + + public static double get31LatitudeY(int tileY){ + return MapUtils.getLatitudeFromTile(21, tileY /1024f); + } + + + + /** + * + * Theses methods operate with degrees (evaluating tiles & vice versa) + * degree longitude measurements (-180, 180) [27.56 Minsk] + // degree latitude measurements (90, -90) [53.9] + */ + + public static double getTileNumberX(float zoom, double longitude){ + if(longitude == 180d) { + return getPowZoom(zoom) - 1; + } + longitude = checkLongitude(longitude); + return (longitude + 180d)/360d * getPowZoom(zoom); + } + + public static double getTileNumberY(float zoom, double latitude){ + latitude = checkLatitude(latitude); + double eval = Math.log( Math.tan(toRadians(latitude)) + 1/Math.cos(toRadians(latitude)) ); + if (Double.isInfinite(eval) || Double.isNaN(eval)) { + latitude = latitude < 0 ? - 89.9 : 89.9; + eval = Math.log( Math.tan(toRadians(latitude)) + 1/Math.cos(toRadians(latitude)) ); + } + double result = (1 - eval / Math.PI) / 2 * getPowZoom(zoom); + return result; + } + + public static double getTileEllipsoidNumberY(float zoom, double latitude){ + final double E2 = (double) latitude * Math.PI / 180; + final long sradiusa = 6378137; + final long sradiusb = 6356752; + final double J2 = (double) Math.sqrt(sradiusa * sradiusa - sradiusb * sradiusb) / sradiusa; + final double M2 = (double) Math.log((1 + Math.sin(E2)) + / (1 - Math.sin(E2)))/ 2- J2 * Math.log((1 + J2 * Math.sin(E2))/ (1 - J2 * Math.sin(E2))) / 2; + final double B2 = getPowZoom(zoom); + return B2 / 2 - M2 * B2 / 2 / Math.PI; + } + + public static double getLatitudeFromEllipsoidTileY(float zoom, float tileNumberY){ + final double MerkElipsK = 0.0000001; + final long sradiusa = 6378137; + final long sradiusb = 6356752; + final double FExct = (double) Math.sqrt(sradiusa * sradiusa + - sradiusb * sradiusb) + / sradiusa; + final double TilesAtZoom = getPowZoom(zoom); + double result = (tileNumberY - TilesAtZoom / 2) + / -(TilesAtZoom / (2 * Math.PI)); + result = (2 * Math.atan(Math.exp(result)) - Math.PI / 2) * 180 + / Math.PI; + double Zu = result / (180 / Math.PI); + double yy = (tileNumberY - TilesAtZoom / 2); + + double Zum1 = Zu; + Zu = Math.asin(1 - ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct * Math.sin(Zum1), FExct)) + / (Math.exp((2 * yy) / -(TilesAtZoom / (2 * Math.PI))) * Math.pow(1 + FExct * Math.sin(Zum1), FExct))); + while (Math.abs(Zum1 - Zu) >= MerkElipsK) { + Zum1 = Zu; + Zu = Math.asin(1 - ((1 + Math.sin(Zum1)) * Math.pow(1 - FExct * Math.sin(Zum1), FExct)) + / (Math.exp((2 * yy) / -(TilesAtZoom / (2 * Math.PI))) * Math.pow(1 + FExct * Math.sin(Zum1), FExct))); + } + + return Zu * 180 / Math.PI; + } + + + public static double getLongitudeFromTile(float zoom, double x) { + return x / getPowZoom(zoom) * 360.0 - 180.0; + } + + public static double getPowZoom(float zoom){ + if(zoom >= 0 && zoom - Math.floor(zoom) < 0.05f){ + return 1 << ((int)zoom); + } else { + return Math.pow(2, zoom); + } + } + + + + public static float calcDiffPixelX(float rotateSin, float rotateCos, float dTileX, float dTileY, float tileSize){ + return (rotateCos * dTileX - rotateSin * dTileY) * tileSize ; + } + + public static float calcDiffPixelY(float rotateSin, float rotateCos, float dTileX, float dTileY, float tileSize){ + return (rotateSin * dTileX + rotateCos * dTileY) * tileSize ; + } + + public static double getLatitudeFromTile(float zoom, double y){ + int sign = y < 0 ? -1 : 1; + double result = Math.atan(sign*Math.sinh(Math.PI * (1 - 2 * y / getPowZoom(zoom)))) * 180d / Math.PI; + return result; + } + + + public static int getPixelShiftX(int zoom, double long1, double long2, int tileSize){ + return (int) ((getTileNumberX(zoom, long1) - getTileNumberX(zoom, long2)) * tileSize); + } + + + public static int getPixelShiftY(int zoom, double lat1, double lat2, int tileSize){ + return (int) ((getTileNumberY(zoom, lat1) - getTileNumberY(zoom, lat2)) * tileSize); + } + + + + public static void sortListOfMapObject(List list, final double lat, final double lon){ + Collections.sort(list, new Comparator() { + @Override + public int compare(MapObject o1, MapObject o2) { + return Double.compare(MapUtils.getDistance(o1.getLocation(), lat, lon), MapUtils.getDistance(o2.getLocation(), + lat, lon)); + } + }); + } + + + // Examples +// System.out.println(buildShortOsmUrl(51.51829d, 0.07347d, 16)); // http://osm.org/go/0EEQsyfu +// System.out.println(buildShortOsmUrl(52.30103d, 4.862927d, 18)); // http://osm.org/go/0E4_JiVhs +// System.out.println(buildShortOsmUrl(40.59d, -115.213d, 9)); // http://osm.org/go/TelHTB-- + public static String buildShortOsmUrl(double latitude, double longitude, int zoom){ + StringBuilder str = new StringBuilder(10); + str.append(BASE_SHORT_OSM_URL); + str.append(createShortLocString(latitude, longitude, zoom)); + str.append("?m"); + return str.toString(); + } + + public static String createShortLocString(double latitude, double longitude, int zoom) { + long lat = (long) (((latitude + 90d)/180d)*(1l << 32)); + long lon = (long) (((longitude + 180d)/360d)*(1l << 32)); + long code = interleaveBits(lon, lat); + String str = ""; + // add eight to the zoom level, which approximates an accuracy of one pixel in a tile. + for (int i = 0; i < Math.ceil((zoom + 8) / 3d); i++) { + str += intToBase64[(int) ((code >> (58 - 6 * i)) & 0x3f)]; + } + // append characters onto the end of the string to represent + // partial zoom levels (characters themselves have a granularity of 3 zoom levels). + for (int j = 0; j < (zoom + 8) % 3; j++) { + str += '-'; + } + return str; + } + + @SuppressWarnings("unused") + public static LatLon decodeShortLocString(String s) { + long x = 0; + long y = 0; + int z = 0; + int z_offset = 0; + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '-') { + z_offset--; + continue; + } + char c = s.charAt(i); + for (int j = 0; j < intToBase64.length; j++) { + if (c == intToBase64[j]) { + for (int k = 0; k < 3; k++) { + x <<= 1; + if ((j & 32) != 0) { + x = x | 1; + } + j <<= 1; + y <<= 1; + if ((j & 32) != 0) { + y = y | 1; + } + j <<= 1; + } + z += 3; + break; + } + } + } + x <<= (32 - z); + y <<= (32 - z); +// int zoom = z - 8 - ((3 + z_offset) % 3); + double dlat = (180d * (y) / ((double)(1l << 32))) - 90d; + double dlon = (360d * (x)/ ((double)(1l << 32))) - 180d; + return new LatLon(dlat, dlon); + } + + /** + * interleaves the bits of two 32-bit numbers. the result is known as a Morton code. + */ + private static long interleaveBits(long x, long y){ + long c = 0; + for(byte b = 31; b>=0; b--){ + c = (c << 1) | ((x >> b) & 1); + c = (c << 1) | ((y >> b) & 1); + } + return c; + } + + /** + * Calculate rotation diff D, that R (rotate) + D = T (targetRotate) + * D is between -180, 180 + * @param rotate + * @param targetRotate + * @return + */ + public static float unifyRotationDiff(float rotate, float targetRotate) { + float d = targetRotate - rotate; + while(d >= 180){ + d -= 360; + } + while(d < -180){ + d += 360; + } + return d; + } + + /** + * Calculate rotation diff D, that R (rotate) + D = T (targetRotate) + * D is between -180, 180 + * @param rotate + * @param targetRotate + * @return + */ + public static float unifyRotationTo360(float rotate) { + while(rotate < 0){ + rotate += 360; + } + while(rotate > 360){ + rotate -= 360; + } + return rotate; + } + + /** + * @param diff align difference between 2 angles ]-PI, PI] + * @return + */ + public static double alignAngleDifference(double diff) { + while(diff > Math.PI) { + diff -= 2 * Math.PI; + } + while(diff <=-Math.PI) { + diff += 2 * Math.PI; + } + return diff; + + } + + /** + * @param diff align difference between 2 angles ]-180, 180] + * @return + */ + public static double degreesDiff(double a1, double a2) { + double diff = a1 - a2; + while(diff > 180) { + diff -= 360; + } + while(diff <=-180) { + diff += 360; + } + return diff; + + } + + + public static double squareDist31TileMetric(int x1, int y1, int x2, int y2) { + // translate into meters + double dy = convert31YToMeters(y1, y2); + double dx = convert31XToMeters(x1, x2); + return dx * dx + dy * dy; + } + public static double convert31YToMeters(float y1, float y2) { + // translate into meters + return (y1 - y2) * 0.01863d; + } + + public static double convert31XToMeters(float x1, float x2) { + // translate into meters + return (x1 - x2) * 0.011d; + } + + + public static double calculateProjection31TileMetric(int xA, int yA, int xB, int yB, int xC, int yC) { + // Scalar multiplication between (AB, AC) + double multiple = convert31XToMeters(xB, xA) * convert31XToMeters(xC, xA) + convert31YToMeters(yB, yA) * convert31YToMeters(yC, yA); + return multiple; + } + +} + + diff --git a/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java b/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java new file mode 100644 index 0000000000..ca53f4727e --- /dev/null +++ b/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java @@ -0,0 +1,600 @@ +package net.osmand.util; + + + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; + + +/** + * Class used to parse opening hours + * + * the method "parseOpenedHours" will parse an OSM opening_hours string and return + * an object of the type OpeningHours. That object can be used to check if the OSM feature + * is open at a certain time. + */ +public class OpeningHoursParser { + private static final String[] daysStr = new String[] {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + /** + * default values for sunrise and sunset. Might be computed afterwards, not final + */ + private static String sunrise = "07:00", sunset = "21:00"; + /** + * hour of when you would expect a day to be ended. + * This is to be used when no end hour is known (like pubs that open at a certain time, + * but close at a variable time, depending on the number of clients). + * OsmAnd needs to show a value, so there is some arbitrary default value chosen. + */ + private static String endOfDay = "24:00"; + + /** + * This class contains the entire OpeningHours schema and + * offers methods to check directly weather something is open + * + * @author sander + */ + public static class OpeningHours { + + /** + * list of the different rules + */ + private ArrayList rules; + + /** + * Constructor + * + * @param rules List of OpeningHoursRule to be given + */ + public OpeningHours(ArrayList rules) { + this.rules = rules; + } + + /** + * Empty constructor + */ + public OpeningHours(){ + rules = new ArrayList(); + } + + /** + * add a rule to the opening hours + * @param r rule to add + */ + public void addRule(OpeningHoursRule r){ + rules.add(r); + } + + /** + * return the list of rules + * + * @return the rules + */ + public ArrayList getRules(){ + return rules; + } + + /** + * check if the feature is opened at time "cal" + * @param cal the time to check + * @return true if feature is open + */ + public boolean isOpenedForTime(Calendar cal){ + /* + * first check for rules that contain the current day + * afterwards check for rules that contain the previous + * day with overlapping times (times after midnight) + */ + boolean isOpenDay = false; + for (OpeningHoursRule r : rules){ + if(r.containsDay(cal)){ + isOpenDay = r.isOpenedForTime(cal, false); + } + } + boolean isOpenPrevious = false; + for (OpeningHoursRule r : rules){ + if(r.containsPreviousDay(cal)){ + isOpenPrevious = r.isOpenedForTime(cal, true); + } + } + return isOpenDay || isOpenPrevious; + } + + @Override + public String toString(){ + StringBuilder s = new StringBuilder(); + + if (rules.isEmpty()) { + return ""; + } + + for (OpeningHoursRule r : rules) { + s.append(r.toString()).append("; "); + } + + return s.substring(0, s.length()-2); + } + + } + + /** + * Interface to represent a single rule + * + * A rule consist out of + * - a collection of days/dates + * - a time range + */ + public static interface OpeningHoursRule { + + /** + * Check if, for this rule, the feature is opened for time "cal" + * @param cal the time to check + * @param checkPrevious only check for overflowing times (after midnight) or don't check for it + * @return true if the feature is open + */ + public boolean isOpenedForTime(Calendar cal, boolean checkPrevious); + + /** + * Check if the previous day before "cal" is part of this rule + * @param cal; the time to check + * @return true if the previous day is part of the rule + */ + public boolean containsPreviousDay(Calendar cal); + + /** + * Check if the day of "cal" is part of this rule + * @param cal; the time to check + * @return true if the day is part of the rule + */ + public boolean containsDay(Calendar cal); + + public String toRuleString(); + } + + /** + * implementation of the basic OpeningHoursRule + * + * This implementation only supports day of weeks and numeral times, or the value "off" + * + */ + public static class BasicDayOpeningHourRule implements OpeningHoursRule { + /** + * represents the list on which days it is open. + * Day number 0 is MONDAY + */ + private boolean[] days = new boolean[7]; + /** + * lists of equal size representing the start and end times + */ + private int[] startTimes = new int[0], endTimes = new int[0]; + + /** + * return an array representing the days of the rule + * @return the days of the rule + */ + public boolean[] getDays() { + return days; + } + + /** + * set a single start time, erase all previously added start times + * @param s startTime to set + */ + public void setStartTime(int s) { + startTimes = new int[]{s}; + if(endTimes.length != 1) { + endTimes = new int[]{0}; + } + } + + /** + * set a single end time, erase all previously added end times + * @param e endTime to set + */ + public void setEndTime(int e) { + endTimes = new int[]{e}; + if(startTimes.length != 1) { + startTimes = new int[]{0}; + } + } + + /** + * get a single start time + * @return a single start time + */ + public int getStartTime() { + if(startTimes.length == 0) { + return 0; + } + return startTimes[0]; + } + + /** + * get a single end time + * @return a single end time + */ + public int getEndTime() { + if(endTimes.length == 0) { + return 0; + } + return endTimes[0]; + } + + + /** + * Check if the weekday of time "cal" is part of this rule + * @param cal the time to check + * @return true if this day is part of the rule + */ + @Override + public boolean containsDay(Calendar cal){ + int i = cal.get(Calendar.DAY_OF_WEEK); + int d = (i + 5) % 7; + if (days[d]) { + return true; + } + return false; + + } + + + /** + * Check if the previous weekday of time "cal" is part of this rule + * @param cal the time to check + * @return true if the previous day is part of the rule + */ + @Override + public boolean containsPreviousDay(Calendar cal){ + int i = cal.get(Calendar.DAY_OF_WEEK); + int p = (i + 4) % 7; + if (days[p]) { + return true; + } + return false; + + } + + /** + * Check if this rule says the feature is open at time "cal" + * @param cal the time to check + * @return true if this rule contains the day to check and the start and end times denote it's open + * @return true if this rule contains the previous day and an endTime>startTime such that the time to check falls before the endtime + * @return false in all other cases, also if only day is wrong + */ + @Override + public boolean isOpenedForTime(Calendar cal, boolean checkPrevious) { + int i = cal.get(Calendar.DAY_OF_WEEK); + int d = (i + 5) % 7; + int p = d - 1; + if (p < 0) { + p += 7; + } + int time = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE); + for (i = 0; i < startTimes.length; i++) { + int startTime = this.startTimes[i]; + int endTime = this.endTimes[i]; + // one day working 10 - 20 (not 20 - 04) + if (startTime < endTime || endTime == -1) { + if (days[d] && !checkPrevious) { + if (time >= startTime && (endTime == -1 || time <= endTime)) { + return true; + } + } + } else { + if (time >= startTime && days[p] && checkPrevious) { + // check in previous day + return true; + } else if (time <= endTime && days[d] && !checkPrevious) { + return true; + } + } + } + return false; + } + + + @Override + public String toRuleString() { + StringBuilder b = new StringBuilder(25); + boolean dash = false; + boolean first = true; + boolean open24_7 = true; + for (int i = 0; i < 7; i++) { + if (days[i]) { + if (i > 0 && days[i - 1] && i < 6 && days[i + 1]) { + if (!dash) { + dash = true; + b.append("-"); //$NON-NLS-1$ + } + continue; + } + if (first) { + first = false; + } else if (!dash) { + b.append(", "); //$NON-NLS-1$ + } + b.append(daysStr[i]); + dash = false; + } else { + open24_7 = false; + } + } + if (startTimes == null || startTimes.length == 0){ + b.append(" off "); + } else { + for (int i = 0; i i){// overflow handling, e.g. Su-We + for (int j = startDay; j <= 6; j++) { + days[j] = true; + } + for (int j = 0; j <= i; j++){ + days[j] = true; + } + } + startDay = -1; + } else { + days[i] = true; + } + previousDay = i; + } + } else { + return false; + } + } + if(previousDay == -1){ + // no days given => take all days. + for (int i = 0; i<7; i++){ + days[i] = true; + } + } + String timeSubstr = r.substring(k); + String[] times = timeSubstr.split(","); + boolean timesExist = true; + for (String time : times) { + time = time.trim(); + if(time.length() == 0){ + continue; + } + if(time.equals("off")){ + break; // add no time values + } + if(time.equals("24/7")){ + // for some reason, this is used. See tagwatch. + basic.addTimeRange(0, 24*60); + break; + } + String[] stEnd = time.split("-"); //$NON-NLS-1$ + if (stEnd.length != 2) { + continue; + } + timesExist = true; + int st; + int end; + try { + int i1 = stEnd[0].indexOf(':'); + int i2 = stEnd[1].indexOf(':'); + int startHour, startMin, endHour, endMin; + if(i1 == -1) { + // if no minutes are given, try complete value as hour + startHour = Integer.parseInt(stEnd[0].trim()); + startMin = 0; + } else { + startHour = Integer.parseInt(stEnd[0].substring(0, i1).trim()); + startMin = Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); + } + if(i2 == -1) { + // if no minutes are given, try complete value as hour + endHour = Integer.parseInt(stEnd[1].trim()); + endMin = 0; + } else { + endHour = Integer.parseInt(stEnd[1].substring(0, i2).trim()); + endMin = Integer.parseInt(stEnd[1].substring(i2 + 1).trim()); + } + st = startHour * 60 + startMin; + end = endHour * 60 + endMin; + } catch (NumberFormatException e) { + return false; + } + basic.addTimeRange(st, end); + } + rs.addRule(basic); + if(!timesExist){ + return false; + } + return true; + } + + /** + * parse OSM opening_hours string to an OpeningHours object + * @param format the string to parse + * @return the OpeningHours object when parsing was successful + * @return null when parsing was unsuccessful + */ + public static OpeningHours parseOpenedHours(String format){ + // split the OSM string in multiple rules + String[] rules = format.split(";"); //$NON-NLS-1$ + OpeningHours rs = new OpeningHours(); + for(String r : rules){ + r = r.trim(); + if(r.length() == 0){ + continue; + } + // check if valid + boolean rule = parseRule(r, rs); + if(!rule){ + return null; + } + } + return rs; + } + + + private static void formatTime(int h, int t, StringBuilder b){ + if(h < 10){ + b.append("0"); //$NON-NLS-1$ + } + b.append(h).append(":"); //$NON-NLS-1$ + if(t < 10){ + b.append("0"); //$NON-NLS-1$ + } + b.append(t); + } + + + private static void testOpened(String time, OpeningHours hours, boolean expected) throws ParseException { + Calendar cal = Calendar.getInstance(); + cal.setTime(new SimpleDateFormat("dd.MM.yyyy HH:mm").parse(time)); + System.out.println("Expected " + time+": " + expected +" = " + hours.isOpenedForTime(cal)); + } + + public static void main(String[] args) throws ParseException { + + + //Test basic case + OpeningHours hours = parseOpenedHours("Mo-Fr 08:30-14:40" ); //$NON-NLS-1$ + System.out.println(hours); + testOpened("09.08.2012 11:00", hours, true); + testOpened("09.08.2012 16:00", hours, false); + // two time and date ranges + hours = parseOpenedHours("Mo-We, Fr 08:30-14:40,15:00-19:00"); //$NON-NLS-1$ + System.out.println(hours); + testOpened("08.08.2012 14:00", hours, true); + testOpened("10.08.2012 15:00", hours, true); + testOpened("08.08.2012 14:50", hours, false); + // test exception on general schema + hours = parseOpenedHours("Mo-Sa 08:30-14:40; Tu 08:00 - 14:00"); //$NON-NLS-1$ + System.out.println(hours); + testOpened("07.08.2012 14:20", hours, false); + // test off value + hours = parseOpenedHours("Mo-Sa 09:00-18:25; Th off"); //$NON-NLS-1$ + System.out.println(hours); + testOpened("08.08.2012 12:00", hours, true); + testOpened("09.08.2012 12:00", hours, false); + //test 24/7 + hours = parseOpenedHours("24/7"); //$NON-NLS-1$ + System.out.println(hours); + testOpened("08.08.2012 23:59", hours, true); + // some people seem to use the following syntax: + hours = parseOpenedHours("Sa-Su 24/7"); + System.out.println(hours); + hours = parseOpenedHours("Mo-Fr 9-19"); + System.out.println(hours); + hours = parseOpenedHours("09:00-17:00"); + System.out.println(hours); + hours = parseOpenedHours("sunrise-sunset"); + System.out.println(hours); + hours = parseOpenedHours("10:00+"); + System.out.println(hours); + hours = parseOpenedHours("Su-Th sunset-24:00, 04:00-sunrise; Fr-Sa sunset-sunrise"); + System.out.println(hours); + testOpened("12.08.2012 04:00", hours, true); + testOpened("12.08.2012 23:00", hours, true); + testOpened("08.08.2012 12:00", hours, false); + testOpened("08.08.2012 05:00", hours, true); + } + +} diff --git a/OsmAnd-java/src/net/osmand/util/SunriseSunset.java b/OsmAnd-java/src/net/osmand/util/SunriseSunset.java new file mode 100644 index 0000000000..c2bb24e95b --- /dev/null +++ b/OsmAnd-java/src/net/osmand/util/SunriseSunset.java @@ -0,0 +1,783 @@ +package net.osmand.util; +/****************************************************************************** +* +* SunriseSunset.java +* +******************************************************************************* +* +* Java Class: SunriseSunset +* +* This Java class is part of a collection of classes developed for the +* reading and processing of oceanographic and meterological data collected +* since 1970 by environmental buoys and stations. This dataset is +* maintained by the National Oceanographic Data Center and is publicly +* available. These Java classes were written for the US Environmental +* Protection Agency's National Exposure Research Laboratory under Contract +* No. GS-10F-0073K with Neptune and Company of Los Alamos, New Mexico. +* +* Purpose: +* +* This Java class performs calculations to determine the time of +* sunrise and sunset given lat, long, and date. +* +* Inputs: +* +* Latitude, longitude, date/time, and time zone. +* +* Outputs: +* +* Local time of sunrise and sunset as calculated by the +* program. +* If no sunrise or no sunset occurs, or if the sun is up all day +* or down all day, appropriate boolean values are set. +* A boolean is provided to identify if the time provided is during the day. +* +* The above values are accessed by the following methods: +* +* Date getSunrise() returns date/time of sunrise +* Date getSunset() returns date/time of sunset +* boolean isSunrise() returns true if there was a sunrise, else false +* boolean isSunset() returns true if there was a sunset, else false +* boolean isSunUp() returns true if sun is up all day, else false +* boolean isSunDown() returns true if sun is down all day, else false +* boolean isDaytime() returns true if sun is up at the time +* specified, else false +* +* Required classes from the Java library: +* +* java.util.Date +* java.text.SimpleDateFormat +* java.text.ParseException; +* java.math.BigDecimal; +* +* Package of which this class is a member: +* +* default +* +* Known limitations: +* +* It is assumed that the data provided are within value ranges +* (i.e. latitude between -90 and +90, longitude between 0 and 360, +* a valid date, and time zone between -14 and +14. +* +* Compatibility: +* +* Java 1.1.8 +* +* References: +* +* The mathematical algorithms used in this program are patterned +* after those debveloped by Roger Sinnott in his BASIC program, +* SUNUP.BAS, published in Sky & Telescope magazine: +* Sinnott, Roger W. "Sunrise and Sunset: A Challenge" +* Sky & Telescope, August, 1994 p.84-85 +* +* The following is a cross-index of variables used in SUNUP.BAS. +* A single definition from multiple reuse of variable names in +* SUNUP.BAS was clarified with various definitions in this program. +* +* SUNUP.BAS this class +* +* A dfA +* A(2) dfAA1, dfAA2 +* A0 dfA0 +* A2 dfA2 +* A5 dfA5 +* AZ Not used +* C dfCosLat +* C0 dfC0 +* D iDay +* D(2) dfDD1, dfDD2 +* D0 dfD0 +* D1 dfD1 +* D2 dfD2 +* D5 dfD5 +* D7 Not used +* DA dfDA +* DD dfDD +* G bGregorian, dfGG +* H dfTimeZone +* H0 dfH0 +* H1 dfH1 +* H2 dfH2 +* H3 dfHourRise, dfHourSet +* H7 Not used +* J dfJ +* J3 dfJ3 +* K1 dfK1 +* L dfLL +* L0 dfL0 +* L2 dfL2 +* L5 dfLon +* M iMonth +* M3 dfMinRise, dfMinSet +* N7 Not used +* P dfP +* S iSign, dfSinLat, dfSS +* T dfT +* T0 dfT0 +* T3 not used +* TT dfTT +* U dfUU +* V dfVV +* V0 dfV0 +* V1 dfV1 +* V2 dfV2 +* W dfWW +* Y iYear +* Z dfZenith +* Z0 dfTimeZone +* +* +* Author/Company: +* +* JDT: John Tauxe, Neptune and Company +* JMG: Jo Marie Green +* +* Change log: +* +* date ver by description of change +* _________ _____ ___ ______________________________________________ +* 5 Jan 01 0.006 JDT Excised from ssapp.java v. 0.005. +* 11 Jan 01 0.007 JDT Minor modifications to comments based on +* material from Sinnott, 1994. +* 7 Feb 01 0.008 JDT Fixed backwards time zone. The standard is that +* local time zone is specified in hours EAST of +* Greenwich, so that EST would be -5, for example. +* For some reason, SUNUP.BAS does this backwards +* (probably an americocentric perspective) and +* SunriseSunset adopted that convention. Oops. +* So the sign in the math is changed. +* 7 Feb 01 0.009 JDT Well, that threw off the azimuth calculation... +* Removed the azimuth calculations. +* 14 Feb 01 0.010 JDT Added ability to accept a time (HH:mm) in +* dateInput, and decide if that time is daytime +* or nighttime. +* 27 Feb 01 0.011 JDT Added accessor methods in place of having public +* variables to get results. +* 28 Feb 01 0.012 JDT Cleaned up list of imported classes. +* 28 Mar 01 1.10 JDT Final version accompanying deliverable 1b. +* 4 Apr 01 1.11 JDT Moved logic supporting .isDaytime into method. +* Moved calculations out of constructor. +* 01 May 01 1.12 JMG Added 'GMT' designation and testing lines. +* 16 May 01 1.13 JDT Added setLenient( false ) and setTimeZone( tz ) +* to dfmtDay, dfmtMonth, and dfmtYear in +* doCalculations. +* 27 Jun 01 1.14 JDT Removed reliance on StationConstants (GMT). +* 13 Aug 01 1.20 JDT Final version accompanying deliverable 1c. +* 6 Sep 01 1.21 JDT Thorough code and comment review. +* 21 Sep 01 1.30 JDT Final version accompanying deliverable 2. +* 17 Dec 01 1.40 JDT Version accompanying final deliverable. +* +*----------------------------------------------------------------------------*/ + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + + +/****************************************************************************** +* class: SunriseSunset class +******************************************************************************* +* +* This Java class performs calculations to determine the time of +* sunrise and sunset given lat, long, and date. +* +* It is assumed that the data provided are within value ranges +* (i.e. latitude between -90 and +90, longitude between 0 and 360, +* a valid date, and time zone between -14 and +14. +* +*----------------------------------------------------------------------------*/ +public class SunriseSunset +{ + + // Declare and initialize variables + private double dfLat; // latitude from user + private double dfLon; // latitude from user + private Date dateInput; // date/time from user + private double dfTimeZone; // time zone from user + + private Date dateSunrise; // date and time of sunrise + private Date dateSunset; // date and time of sunset + private boolean bSunriseToday = false; // flag for sunrise on this date + private boolean bSunsetToday = false; // flag for sunset on this date + private boolean bSunUpAllDay = false; // flag for sun up all day + private boolean bSunDownAllDay = false; // flag for sun down all day + private boolean bDaytime = false; // flag for daytime, given + // hour and min in dateInput + private boolean bSunrise = false; // sunrise during hour checked + private boolean bSunset = false; // sunset during hour checked + private boolean bGregorian = false; // flag for Gregorian calendar + private int iJulian; // Julian day + private int iYear; // year of date of interest + private int iMonth; // month of date of interest + private int iDay; // day of date of interest + private int iCount; // a simple counter + private int iSign; // SUNUP.BAS: S + private int dfHourRise, dfHourSet; // hour of event: SUNUP.BAS H3 + private int dfMinRise, dfMinSet; // minute of event: SUNUP.BAS M3 + private double dfSinLat, dfCosLat; // sin and cos of latitude + private double dfZenith; // SUNUP.BAS Z: Zenith + // Many variables in SUNUP.BAS have undocumented meanings, + // and so are translated rather directly to avoid confusion: + private double dfAA1 = 0, dfAA2 = 0; // SUNUP.BAS A(2) + private double dfDD1 = 0, dfDD2 = 0; // SUNUP.BAS D(2) + private double dfC0; // SUNUP.BAS C0 + private double dfK1; // SUNUP.BAS K1 + private double dfP; // SUNUP.BAS P + private double dfJ; // SUNUP.BAS J + private double dfJ3; // SUNUP.BAS J3 + private double dfA; // SUNUP.BAS A + private double dfA0, dfA2, dfA5; // SUNUP.BAS A0, A2, A5 + private double dfD0, dfD1, dfD2, dfD5; // SUNUP.BAS D0, D1, D2, D5 + private double dfDA, dfDD; // SUNUP.BAS DA, DD + private double dfH0, dfH1, dfH2; // SUNUP.BAS H0, H1, H2 + private double dfL0, dfL2; // SUNUP.BAS L0, L2 + private double dfT, dfT0, dfTT; // SUNUP.BAS T, T0, TT + private double dfV0, dfV1, dfV2; // SUNUP.BAS V0, V1, V2 + + +/****************************************************************************** +* method: SunriseSunset +******************************************************************************* +* +* Constructor for SunriseSunset class. +* +*----------------------------------------------------------------------------*/ + public SunriseSunset( + double dfLatIn, // latitude + double dfLonIn, // longitude + Date dateInputIn, // date + TimeZone tzIn // time zone + ) + { + // Calculate internal representation of timezone offset as fraction of hours from GMT + // Our calculations consider offsets to the West as positive, so we must invert + // the signal of the values provided by the standard library + double dfTimeZoneIn = 1.0 * tzIn.getOffset(dateInputIn.getTime()) / 3600000; + + // Copy values supplied as agruments to local variables. + dfLat = dfLatIn; + dfLon = dfLonIn; + dateInput = dateInputIn; + dfTimeZone = dfTimeZoneIn; + + // Call the method to do the calculations. + doCalculations(); + + } // end of class constructor + + +/****************************************************************************** +* method: doCalculations +******************************************************************************* +* +* Method for performing the calculations done in SUNUP.BAS. +* +*----------------------------------------------------------------------------*/ + private void doCalculations() + { + // Break out day, month, and year from date provided using local time zone. + // (This is necessary for the math algorithms.) + Calendar cin = Calendar.getInstance(); + cin.setTime(dateInput); + + iYear = cin.get(Calendar.YEAR); + iMonth = cin.get(Calendar.MONTH) + 1; + iDay = cin.get(Calendar.DAY_OF_MONTH); + + // Convert time zone hours to decimal days (SUNUP.BAS line 50) + dfTimeZone = dfTimeZone / 24.0; + + // NOTE: (7 Feb 2001) Here is a non-standard part of SUNUP.BAS: + // It (and this algorithm) assumes that the time zone is + // positive west, instead of the standard negative west. + // Classes calling SunriseSunset will be assuming that + // times zones are specified in negative west, so here the + // sign is changed so that the SUNUP algorithm works: + dfTimeZone = -dfTimeZone; + + // Convert longitude to fraction (SUNUP.BAS line 50) + dfLon = dfLon / 360.0; + + // Convert calendar date to Julian date: + // Check to see if it's later than 1583: Gregorian calendar + // When declared, bGregorian is initialized to false. + // ** Consider making a separate class of this function. ** + if( iYear >= 1583 ) bGregorian = true; + // SUNUP.BAS 1210 + dfJ = -Math.floor( 7.0 // SUNUP used INT, not floor + * ( Math.floor( + ( iMonth + 9.0 ) + / 12.0 + ) + iYear + ) / 4.0 + ) + // add SUNUP.BAS 1240 and 1250 for G = 0 + + Math.floor( iMonth * 275.0 / 9.0 ) + + iDay + + 1721027.0 + + iYear * 367.0; + + if ( bGregorian ) + { + // SUNUP.BAS 1230 + if ( ( iMonth - 9.0 ) < 0.0 ) iSign = -1; + else iSign = 1; + dfA = Math.abs( iMonth - 9.0 ); + // SUNUP.BAS 1240 and 1250 + dfJ3 = -Math.floor( + ( + Math.floor( + Math.floor( iYear + + (double)iSign + * Math.floor( dfA / 7.0 ) + ) + / 100.0 + ) + 1.0 + ) * 0.75 + ); + // correct dfJ as in SUNUP.BAS 1240 and 1250 for G = 1 + dfJ = dfJ + dfJ3 + 2.0; + } + // SUNUP.BAS 1290 + iJulian = (int)dfJ - 1; + + // SUNUP.BAS 60 and 70 (see also line 1290) + dfT = (double)iJulian - 2451545.0 + 0.5; + dfTT = dfT / 36525.0 + 1.0; // centuries since 1900 + + // Calculate local sidereal time at 0h in zone time + // SUNUP.BAS 410 through 460 + dfT0 = ( dfT * 8640184.813 / 36525.0 + + 24110.5 + + dfTimeZone * 86636.6 + + dfLon * 86400.0 + ) + / 86400.0; + dfT0 = dfT0 - Math.floor( dfT0 ); // NOTE: SUNUP.BAS uses INT() + dfT0 = dfT0 * 2.0 * Math.PI; + // SUNUP.BAS 90 + dfT = dfT + dfTimeZone; + + // SUNUP.BAS 110: Get Sun's position + for( iCount=0; iCount<=1; iCount++ ) // Loop thru only twice + { + // Calculate Sun's right ascension and declination + // at the start and end of each day. + // SUNUP.BAS 910 - 1160: Fundamental arguments + // from van Flandern and Pulkkinen, 1979 + + // declare local temporary doubles for calculations + double dfGG; // SUNUP.BAS G + double dfLL; // SUNUP.BAS L + double dfSS; // SUNUP.BAS S + double dfUU; // SUNUP.BAS U + double dfVV; // SUNUP.BAS V + double dfWW; // SUNUP.BAS W + + dfLL = 0.779072 + 0.00273790931 * dfT; + dfLL = dfLL - Math.floor( dfLL ); + dfLL = dfLL * 2.0 * Math.PI; + + dfGG = 0.993126 + 0.0027377785 * dfT; + dfGG = dfGG - Math.floor( dfGG ); + dfGG = dfGG * 2.0 * Math.PI; + + dfVV = 0.39785 * Math.sin( dfLL ) + - 0.01000 * Math.sin( dfLL - dfGG ) + + 0.00333 * Math.sin( dfLL + dfGG ) + - 0.00021 * Math.sin( dfLL ) * dfTT; + + dfUU = 1 + - 0.03349 * Math.cos( dfGG ) + - 0.00014 * Math.cos( dfLL * 2.0 ) + + 0.00008 * Math.cos( dfLL ); + + dfWW = - 0.00010 + - 0.04129 * Math.sin( dfLL * 2.0 ) + + 0.03211 * Math.sin( dfGG ) + - 0.00104 * Math.sin( 2.0 * dfLL - dfGG ) + - 0.00035 * Math.sin( 2.0 * dfLL + dfGG ) + - 0.00008 * Math.sin( dfGG ) * dfTT; + + // Compute Sun's RA and Dec; SUNUP.BAS 1120 - 1140 + dfSS = dfWW / Math.sqrt( dfUU - dfVV * dfVV ); + dfA5 = dfLL + + Math.atan( dfSS / Math.sqrt( 1.0 - dfSS * dfSS )); + + dfSS = dfVV / Math.sqrt( dfUU ); + dfD5 = Math.atan( dfSS / Math.sqrt( 1 - dfSS * dfSS )); + + // Set values and increment t + if ( iCount == 0 ) // SUNUP.BAS 125 + { + dfAA1 = dfA5; + dfDD1 = dfD5; + } + else // SUNUP.BAS 145 + { + dfAA2 = dfA5; + dfDD2 = dfD5; + } + dfT = dfT + 1.0; // SUNUP.BAS 130 + } // end of Get Sun's Position for loop + + if ( dfAA2 < dfAA1 ) dfAA2 = dfAA2 + 2.0 * Math.PI; + // SUNUP.BAS 150 + + dfZenith = Math.PI * 90.833 / 180.0; // SUNUP.BAS 160 + dfSinLat = Math.sin( dfLat * Math.PI / 180.0 ); // SUNUP.BAS 170 + dfCosLat = Math.cos( dfLat * Math.PI / 180.0 ); // SUNUP.BAS 170 + + dfA0 = dfAA1; // SUNUP.BAS 190 + dfD0 = dfDD1; // SUNUP.BAS 190 + dfDA = dfAA2 - dfAA1; // SUNUP.BAS 200 + dfDD = dfDD2 - dfDD1; // SUNUP.BAS 200 + + dfK1 = 15.0 * 1.0027379 * Math.PI / 180.0; // SUNUP.BAS 330 + + // Initialize sunrise and sunset times, and other variables + // hr and min are set to impossible times to make errors obvious + dfHourRise = 99; + dfMinRise = 99; + dfHourSet = 99; + dfMinSet = 99; + dfV0 = 0.0; // initialization implied by absence in SUNUP.BAS + dfV2 = 0.0; // initialization implied by absence in SUNUP.BAS + + // Test each hour to see if the Sun crosses the horizon + // and which way it is heading. + for( iCount=0; iCount<24; iCount++ ) // SUNUP.BAS 210 + { + double tempA; // SUNUP.BAS A + double tempB; // SUNUP.BAS B + double tempD; // SUNUP.BAS D + double tempE; // SUNUP.BAS E + + dfC0 = (double)iCount; + dfP = ( dfC0 + 1.0 ) / 24.0; // SUNUP.BAS 220 + dfA2 = dfAA1 + dfP * dfDA; // SUNUP.BAS 230 + dfD2 = dfDD1 + dfP * dfDD; // SUNUP.BAS 230 + dfL0 = dfT0 + dfC0 * dfK1; // SUNUP.BAS 500 + dfL2 = dfL0 + dfK1; // SUNUP.BAS 500 + dfH0 = dfL0 - dfA0; // SUNUP.BAS 510 + dfH2 = dfL2 - dfA2; // SUNUP.BAS 510 + // hour angle at half hour + dfH1 = ( dfH2 + dfH0 ) / 2.0; // SUNUP.BAS 520 + // declination at half hour + dfD1 = ( dfD2 + dfD0 ) / 2.0; // SUNUP.BAS 530 + + // Set value of dfV0 only if this is the first hour, + // otherwise, it will get set to the last dfV2 (SUNUP.BAS 250) + if ( iCount == 0 ) // SUNUP.BAS 550 + { + dfV0 = dfSinLat * Math.sin( dfD0 ) + + dfCosLat * Math.cos( dfD0 ) * Math.cos( dfH0 ) + - Math.cos( dfZenith ); // SUNUP.BAS 560 + } + else + dfV0 = dfV2; // That is, dfV2 from the previous hour. + + dfV2 = dfSinLat * Math.sin( dfD2 ) + + dfCosLat * Math.cos( dfD2 ) * Math.cos( dfH2 ) + - Math.cos( dfZenith ); // SUNUP.BAS 570 + + // if dfV0 and dfV2 have the same sign, then proceed to next hr + if ( + ( dfV0 >= 0.0 && dfV2 >= 0.0 ) // both are positive + || // or + ( dfV0 < 0.0 && dfV2 < 0.0 ) // both are negative + ) + { + // Break iteration and proceed to test next hour + dfA0 = dfA2; // SUNUP.BAS 250 + dfD0 = dfD2; // SUNUP.BAS 250 + continue; // SUNUP.BAS 610 + } + + dfV1 = dfSinLat * Math.sin( dfD1 ) + + dfCosLat * Math.cos( dfD1 ) * Math.cos( dfH1 ) + - Math.cos( dfZenith ); // SUNUP.BAS 590 + + tempA = 2.0 * dfV2 - 4.0 * dfV1 + 2.0 * dfV0; + // SUNUP.BAS 600 + tempB = 4.0 * dfV1 - 3.0 * dfV0 - dfV2; // SUNUP.BAS 600 + tempD = tempB * tempB - 4.0 * tempA * dfV0; // SUNUP.BAS 610 + + if ( tempD < 0.0 ) + { + // Break iteration and proceed to test next hour + dfA0 = dfA2; // SUNUP.BAS 250 + dfD0 = dfD2; // SUNUP.BAS 250 + continue; // SUNUP.BAS 610 + } + + tempD = Math.sqrt( tempD ); // SUNUP.BAS 620 + + // Determine occurence of sunrise or sunset. + + // Flags to identify occurrence during this day are + // bSunriseToday and bSunsetToday, and are initialized false. + // These are set true only if sunrise or sunset occurs + // at any point in the hourly loop. Never set to false. + + // Flags to identify occurrence during this hour: + bSunrise = false; // reset before test + bSunset = false; // reset before test + + if ( dfV0 < 0.0 && dfV2 > 0.0 ) // sunrise occurs this hour + { + bSunrise = true; // SUNUP.BAS 640 + bSunriseToday = true; // sunrise occurred today + } + + if ( dfV0 > 0.0 && dfV2 < 0.0 ) // sunset occurs this hour + { + bSunset = true; // SUNUP.BAS 660 + bSunsetToday = true; // sunset occurred today + } + + tempE = ( tempD - tempB ) / ( 2.0 * tempA ); + if ( tempE > 1.0 || tempE < 0.0 ) // SUNUP.BAS 670, 680 + tempE = ( -tempD - tempB ) / ( 2.0 * tempA ); + + // Set values of hour and minute of sunset or sunrise + // only if sunrise/set occurred this hour. + if ( bSunrise ) + { + dfHourRise = (int)( dfC0 + tempE + 1.0/120.0 ); + dfMinRise = (int) ( + ( dfC0 + tempE + 1.0/120.0 + - dfHourRise + ) + * 60.0 + ); + } + + if ( bSunset ) + { + dfHourSet = (int) ( dfC0 + tempE + 1.0/120.0 ); + dfMinSet = (int)( + ( dfC0 + tempE + 1.0/120.0 + - dfHourSet + ) + * 60.0 + ); + } + + // Change settings of variables for next loop + dfA0 = dfA2; // SUNUP.BAS 250 + dfD0 = dfD2; // SUNUP.BAS 250 + + } // end of loop testing each hour for an event + + // After having checked all hours, set flags if no rise or set + // bSunUpAllDay and bSundownAllDay are initialized as false + if ( !bSunriseToday && !bSunsetToday ) + { + if ( dfV2 < 0.0 ) + bSunDownAllDay = true; + else + bSunUpAllDay = true; + } + + // Load dateSunrise with data + + if( bSunriseToday ) + { + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, iYear); + c.set(Calendar.MONTH, iMonth-1); + c.set(Calendar.DAY_OF_MONTH, iDay); + c.set(Calendar.HOUR_OF_DAY, dfHourRise); + c.set(Calendar.MINUTE, dfMinRise); + dateSunrise = c.getTime(); + } + + // Load dateSunset with data + if( bSunsetToday ) + { + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, iYear); + c.set(Calendar.MONTH, iMonth-1); + c.set(Calendar.DAY_OF_MONTH, iDay); + c.set(Calendar.HOUR_OF_DAY, dfHourSet); + c.set(Calendar.MINUTE, dfMinSet); + dateSunset = c.getTime(); + } + } + + +/****************************************************************************** +* method: getSunrise() +******************************************************************************* +* +* Gets the date and time of sunrise. If there is no sunrise, returns null. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public Date getSunrise() + { + if ( bSunriseToday ) + return( dateSunrise ); + else + return( null ); + } + + +/****************************************************************************** +* method: getSunset() +******************************************************************************* +* +* Gets the date and time of sunset. If there is no sunset, returns null. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public Date getSunset() + { + if ( bSunsetToday ) + return( dateSunset ); + else + return( null ); + } + + +/****************************************************************************** +* method: isSunrise() +******************************************************************************* +* +* Returns a boolean identifying if there was a sunrise. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public boolean isSunrise() + { + return( bSunriseToday ); + } + + +/****************************************************************************** +* method: isSunset() +******************************************************************************* +* +* Returns a boolean identifying if there was a sunset. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public boolean isSunset() + { + return( bSunsetToday ); + } + + +/****************************************************************************** +* method: isSunUp() +******************************************************************************* +* +* Returns a boolean identifying if the sun is up all day. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public boolean isSunUp() + { + return( bSunUpAllDay ); + } + + +/****************************************************************************** +* method: isSunDown() +******************************************************************************* +* +* Returns a boolean identifying if the sun is down all day. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public boolean isSunDown() + { + return( bSunDownAllDay ); + } + + +/****************************************************************************** +* method: isDaytime() +******************************************************************************* +* +* Returns a boolean identifying if it is daytime at the hour contained in +* the Date object passed to SunriseSunset on construction. +* +* Member of SunriseSunset class +* +* -------------------------------------------------------------------------- */ + public boolean isDaytime() + { + // Determine if it is daytime (at sunrise or later) + // or nighttime (at sunset or later) at the location of interest + // but expressed in the time zone requested. + if ( bSunriseToday && bSunsetToday ) // sunrise and sunset + { + if ( dateSunrise.before( dateSunset ) ) // sunrise < sunset + { + if ( + ( + dateInput.after( dateSunrise ) + || + dateInput.equals( dateSunrise ) + ) + && + dateInput.before( dateSunset ) + ) + bDaytime = true; + else + bDaytime = false; + } + else // sunrise comes after sunset (in opposite time zones) + { + if ( + ( + dateInput.after( dateSunrise ) + || + dateInput.equals( dateSunrise ) + ) + || // use OR rather than AND + dateInput.before( dateSunset ) + ) + bDaytime = true; + else + bDaytime = false; + } + } + else if ( bSunUpAllDay ) // sun is up all day + bDaytime = true; + else if ( bSunDownAllDay ) // sun is down all day + bDaytime = false; + else if ( bSunriseToday ) // sunrise but no sunset + { + if ( dateInput.before( dateSunrise ) ) + bDaytime = false; + else + bDaytime = true; + } + else if ( bSunsetToday ) // sunset but no sunrise + { + if ( dateInput.before( dateSunset ) ) + bDaytime = true; + else + bDaytime = false; + } + else bDaytime = false; // this should never execute + + return( bDaytime ); + } +} // end of class + +/*----------------------------------------------------------------------------- +* end of class +*----------------------------------------------------------------------------*/ + diff --git a/OsmAnd/.project b/OsmAnd/.project index 0be0750287..382056b655 100644 --- a/OsmAnd/.project +++ b/OsmAnd/.project @@ -108,7 +108,7 @@ use 2 - OSMAND_TRUNK/jni/java + OSMAND_TRUNK/android/OsmAnd-java/src diff --git a/OsmAnd/build.xml b/OsmAnd/build.xml index 0433a13c75..8d673be932 100644 --- a/OsmAnd/build.xml +++ b/OsmAnd/build.xml @@ -11,7 +11,7 @@ unless="sdk.dir" /> - +