Package org.openstreetmap.osmosis.core.domain.v0_6

Source Code of org.openstreetmap.osmosis.core.domain.v0_6.CommonEntityData

// This software is released into the Public Domain.  See copying.txt for details.
package org.openstreetmap.osmosis.core.domain.v0_6;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.openstreetmap.osmosis.core.OsmosisRuntimeException;
import org.openstreetmap.osmosis.core.domain.common.SimpleTimestampContainer;
import org.openstreetmap.osmosis.core.domain.common.TimestampContainer;
import org.openstreetmap.osmosis.core.domain.common.TimestampFormat;
import org.openstreetmap.osmosis.core.store.StoreClassRegister;
import org.openstreetmap.osmosis.core.store.StoreReader;
import org.openstreetmap.osmosis.core.store.StoreWriter;
import org.openstreetmap.osmosis.core.store.Storeable;
import org.openstreetmap.osmosis.core.util.LazyHashMap;
import org.openstreetmap.osmosis.core.util.LongAsInt;


/**
* Contains data common to all entity types. This is separated from the entity class to allow it to
* be instantiated before all the data required for a full entity is available.
*/
public class CommonEntityData implements Storeable {
 
  private long id;
  private int version;
  private int changesetId;
  private TimestampContainer timestampContainer;
  private OsmUser user;
  private TagCollection tags;
  private Map<String, Object> metaTags;
  private boolean readOnly;
 
 
  /**
   * Creates a new instance.
   *
   * @param id
   *            The unique identifier.
   * @param version
   *            The version of the entity.
   * @param timestamp
   *            The last updated timestamp.
   * @param user
   *            The user that last modified this entity.
   * @param changesetId
   *            The id of the changeset that this version of the entity was created by.
   */
  public CommonEntityData(long id, int version, Date timestamp, OsmUser user, long changesetId) {
    // Chain to the more specific constructor
    this(id, version, new SimpleTimestampContainer(timestamp), user, changesetId);
  }
 
 
  /**
   * Creates a new instance.
   *
   * @param id
   *            The unique identifier.
   * @param version
   *            The version of the entity.
   * @param timestampContainer
   *            The container holding the timestamp in an alternative
   *            timestamp representation.
   * @param user
   *            The user that last modified this entity.
   * @param changesetId
   *            The id of the changeset that this version of the entity was created by.
   */
  public CommonEntityData(
      long id, int version, TimestampContainer timestampContainer, OsmUser user, long changesetId) {
    init(id, timestampContainer, user, version, changesetId);
    tags = new TagCollectionImpl();
    metaTags = new LazyHashMap<String, Object>();
  }
 
 
  /**
   * Creates a new instance.
   *
   * @param id
   *            The unique identifier.
   * @param version
   *            The version of the entity.
   * @param timestamp
   *            The last updated timestamp.
   * @param user
   *            The user that last modified this entity.
   * @param changesetId
   *            The id of the changeset that this version of the entity was created by.
   * @param tags
   *            The tags to apply to the object.
   */
  public CommonEntityData(
      long id, int version, Date timestamp, OsmUser user, long changesetId, Collection<Tag> tags) {
    // Chain to the more specific constructor
    this(id, version, new SimpleTimestampContainer(timestamp), user, changesetId, tags);
  }
 
 
  /**
   * Creates a new instance.
   *
   * @param id
   *            The unique identifier.
   * @param version
   *            The version of the entity.
   * @param timestampContainer
   *            The container holding the timestamp in an alternative
   *            timestamp representation.
   * @param user
   *            The user that last modified this entity.
   * @param changesetId
   *            The id of the changeset that this version of the entity was created by.
   * @param tags
   *            The tags to apply to the object.
   */
  public CommonEntityData(long id, int version, TimestampContainer timestampContainer, OsmUser user, long changesetId,
      Collection<Tag> tags) {
    init(id, timestampContainer, user, version, changesetId);
    this.tags = new TagCollectionImpl(tags);
    metaTags = new LazyHashMap<String, Object>();
  }


  /**
   * Initializes non-collection attributes.
   *
   * @param newId
   *            The unique identifier.
   * @param newTimestampContainer
   *            The container holding the timestamp in an alternative timestamp representation.
   * @param newUser
   *            The user that last modified this entity.
   * @param newVersion
   *            The version of the entity.
   * @param changesetId
   *            The id of the changeset that this version of the entity was created by.
   */
  private void init(long newId, TimestampContainer newTimestampContainer, OsmUser newUser, int newVersion,
      long newChangesetId) {
    this.id = newId;
    this.timestampContainer = newTimestampContainer;
    this.user = newUser;
    this.version = newVersion;
    this.changesetId = LongAsInt.longToInt(newChangesetId);
  }
 
 
  private static TimestampContainer readTimestampContainer(StoreReader sr, StoreClassRegister scr) {
    if (sr.readBoolean()) {
      return new SimpleTimestampContainer(new Date(sr.readLong()));
    } else {
      return null;
    }
  }
 
 
  private static OsmUser readOsmUser(StoreReader sr, StoreClassRegister scr) {
    OsmUser user;
   
    // We could follow the same approach as timestamps and use a boolean to
    // indicate the existence of a user or not. But most entities have a
    // user so this would increase the space consumed on disk. So I'm taking
    // a small hit in instantiating unnecessary OsmUser objects when no user
    // is available.
    user = new OsmUser(sr, scr);
   
    if (user.equals(OsmUser.NONE)) {
      return OsmUser.NONE;
    } else {
      return user;
    }
  }
 
 
  /**
   * Creates a new instance.
   *
   * @param sr
   *            The store to read state from.
   * @param scr
   *            Maintains the mapping between classes and their identifiers
   *            within the store.
   */
  public CommonEntityData(StoreReader sr, StoreClassRegister scr) {
    this(
      sr.readLong(),
      sr.readInteger(),
      readTimestampContainer(sr, scr),
      readOsmUser(sr, scr),
      sr.readInteger(),
      new TagCollectionImpl(sr, scr)
    );
   
    int metaTagCount;
   
    metaTagCount = sr.readInteger();
    metaTags = new LazyHashMap<String, Object>();
    for (int i = 0; i < metaTagCount; i++) {
      metaTags.put(sr.readString(), sr.readString());
    }
  }
 
 
  /**
   * {@inheritDoc}
   */
  public void store(StoreWriter sw, StoreClassRegister scr) {
    sw.writeLong(id);
   
    sw.writeInteger(version);
   
    if (getTimestamp() != null) {
      sw.writeBoolean(true);
      sw.writeLong(timestampContainer.getTimestamp().getTime());
    } else {
      sw.writeBoolean(false);
    }
   
    user.store(sw, scr);
   
    sw.writeInteger(changesetId);
   
    tags.store(sw, scr);
   
    sw.writeInteger(metaTags.size());
    for (Entry<String, Object> tag : metaTags.entrySet()) {
      sw.writeString(tag.getKey());
      sw.writeString(tag.getValue().toString());
    }
  }
 
 
  /**
   * Compares the tags on this entity to the specified tags. The tag
   * comparison is based on a comparison of key and value in that order.
   *
   * @param comparisonTags
   *            The tags to compare to.
   * @return 0 if equal, &lt; 0 if considered "smaller", and &gt; 0 if considered
   *         "bigger".
   */
  protected int compareTags(Collection<Tag> comparisonTags) {
    List<Tag> tags1;
    List<Tag> tags2;
   
    tags1 = new ArrayList<Tag>(tags);
    tags2 = new ArrayList<Tag>(comparisonTags);
   
    Collections.sort(tags1);
    Collections.sort(tags2);
   
    // The list with the most tags is considered bigger.
    if (tags1.size() != tags2.size()) {
      return tags1.size() - tags2.size();
    }
   
    // Check the individual tags.
    for (int i = 0; i < tags1.size(); i++) {
      int result = tags1.get(i).compareTo(tags2.get(i));
     
      if (result != 0) {
        return result;
      }
    }
   
    // There are no differences.
    return 0;
  }


  /**
   * Gets the identifier.
   *
   * @return The id.
   */
  public long getId() {
    return id;
  }


  /**
   * Sets the identifier.
   *
   * @param id
   *            The identifier.
   */
  public void setId(long id) {
    assertWriteable();
   
    this.id = id;
  }
 
 
  /**
   * Gets the version.
   *
   * @return The version.
   */
  public int getVersion() {
    return version;
  }


  /**
   * Sets the version.
   *
   * @param version
   *            The version.
   */
  public void setVersion(int version) {
    assertWriteable();
   
    this.version = version;
  }
 
 
  /**
   * Gets the timestamp in date form. This is the standard method for
   * retrieving timestamp information.
   *
   * @return The timestamp.
   */
  public Date getTimestamp() {
    return timestampContainer.getTimestamp();
  }


  /**
   * Sets the timestamp in date form. This is the standard method of updating a timestamp.
   *
   * @param timestamp
   *            The timestamp.
   */
  public void setTimestamp(Date timestamp) {
    assertWriteable();
   
    timestampContainer = new SimpleTimestampContainer(timestamp);
  }
 
 
  /**
   * Gets the timestamp container object which may hold the timestamp in a
   * different format. This is most useful if creating new copies of entities
   * because it can avoid the need to parse timestamp information into Date
   * form.
   *
   * @return The timestamp container.
   */
  public TimestampContainer getTimestampContainer() {
    return timestampContainer;
  }
 
 
  /**
   * Sets the timestamp container object allowing the timestamp to be held in a different format.
   * This should be used if a date is already held in a timestamp container, or if date parsing
   * can be avoided.
   *
   * @param timestampContainer
   *            The timestamp container.
   */
  public void setTimestampContainer(TimestampContainer timestampContainer) {
    assertWriteable();
   
    this.timestampContainer = timestampContainer;
  }
 
 
  /**
   * Gets the timestamp in a string format. If the entity already contains a
   * string in string format it will return the original unparsed string
   * instead of formatting a date object.
   *
   * @param timestampFormat
   *            The formatter to use for formatting the timestamp into a
   *            string.
   * @return The timestamp string.
   */
  public String getFormattedTimestamp(TimestampFormat timestampFormat) {
    return timestampContainer.getFormattedTimestamp(timestampFormat);
  }
 
 
  /**
   * Returns the user who last edited the entity.
   *
   * @return The user.
   */
  public OsmUser getUser() {
    return user;
  }
 
 
  /**
   * Sets the last modification user.
   *
   * @param user
   *            The user.
   */
  public void setUser(OsmUser user) {
    assertWriteable();
   
    this.user = user;
  }
 
 
  /**
   * Gets the id of the changeset that this version of the entity was created by.
   *
   * @return The changeset id.
   */
  public long getChangesetId() {
    return changesetId;
  }
 
 
  /**
   * Sets the id of the changeset that this version of the entity was created by.
   *
   * @param changesetId
   *            The changeset id.
   */
  public void setChangesetId(long changesetId) {
    assertWriteable();
   
    this.changesetId = LongAsInt.longToInt(changesetId);
  }


  /**
   * Returns the attached tags. If the class is read-only, the collection will
   * be read-only.
   *
   * @return The tags.
   */
  public Collection<Tag> getTags() {
    return tags;
  }


  /**
   * Returns the attached meta tags. If the class is read-only, the collection will
   * be read-only.
   *
   * @return The metaTags.
   */
  public Map<String, Object> getMetaTags() {
    return metaTags;
  }


  /**
   * Indicates if the object has been set to read-only. A read-only object
   * must be cloned in order to make updates. This allows objects shared
   * between multiple threads to be locked for thread safety.
   *
   * @return True if the object is read-only.
   */
  public boolean isReadOnly() {
    return readOnly;
  }


  /**
   * Ensures that the object is writeable. If not an exception will be thrown.
   * This is intended to be called within all update methods.
   */
  protected void assertWriteable() {
    if (readOnly) {
      throw new OsmosisRuntimeException(
          "The object has been marked as read-only.  It must be cloned to make changes.");
    }
  }


  /**
   * Configures the object to be read-only. This should be called if the object is to be processed
   * by multiple threads concurrently. It updates the read-only status of the object, and makes
   * all collections unmodifiable. This must be overridden by sub-classes to make their own
   * collections unmodifiable.
   */
  public void makeReadOnly() {
    if (!readOnly) {
      tags = new UnmodifiableTagCollection(tags);
      metaTags = Collections.unmodifiableMap(metaTags);
     
      readOnly = true;
    }
  }


  /**
   * Returns a writable instance of this object. If the object is read-only a clone is created,
   * if it is already writable then this object is returned.
   *
   * @return A writable instance of this object.
   */
  public CommonEntityData getWriteableInstance() {
    if (isReadOnly()) {
      return new CommonEntityData(id, version, timestampContainer, user, changesetId, tags);
    } else {
      return this;
    }
  }
}
TOP

Related Classes of org.openstreetmap.osmosis.core.domain.v0_6.CommonEntityData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.