All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.api.client.util.GenericData Maven / Gradle / Ivy

Go to download

Google API Client Library for Java. Supports Java 5 (or higher) desktop (SE) and web (EE), Android, and Google App Engine.

There is a newer version: 1.4.1-beta
Show newest version
/*
 * Copyright (c) 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.api.client.util;

import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Generic data that stores all unknown data key name/value pairs.
 * 

* Subclasses can declare fields for known data keys using the {@link Key} * annotation. Each field can be of any visibility (private, package private, * protected, or public) and must not be static. {@code null} unknown data key * names are not allowed, but {@code null} data values are allowed. *

* Iteration order of the data keys is based on the sorted (ascending) key names * of the declared fields, followed by the iteration order of all of the unknown * data key name/value pairs. * * @since 1.0 * @author Yaniv Inbar */ public class GenericData extends AbstractMap implements Cloneable { // TODO: type parameter to specify value type? private EntrySet entrySet; /** Map of unknown fields. */ public ArrayMap unknownFields = ArrayMap.create(); // TODO: implement more methods for faster implementation private final ClassInfo classInfo = ClassInfo.of(getClass()); @Override public int size() { return this.classInfo.getKeyCount() + unknownFields.size(); } @Override public final Object get(Object name) { if (!(name instanceof String)) { return null; } String fieldName = (String) name; FieldInfo fieldInfo = this.classInfo.getFieldInfo(fieldName); if (fieldInfo != null) { return fieldInfo.getValue(this); } return this.unknownFields.get(fieldName); } @Override public final Object put(String name, Object value) { FieldInfo fieldInfo = this.classInfo.getFieldInfo(name); if (fieldInfo != null) { Object oldValue = fieldInfo.getValue(this); fieldInfo.setValue(this, value); return oldValue; } return this.unknownFields.put(name, value); } /** * Sets the given field value (may be {@code null}) for the given field name. * Any existing value for the field will be overwritten. It may be more * slightly more efficient than {@link #put(String, Object)} because it avoids * accessing the field's original value. */ public final void set(String name, Object value) { FieldInfo fieldInfo = this.classInfo.getFieldInfo(name); if (fieldInfo != null) { fieldInfo.setValue(this, value); return; } this.unknownFields.put(name, value); } @Override public final void putAll(Map map) { for (Map.Entry entry : map.entrySet()) { set(entry.getKey(), entry.getValue()); } } @Override public final Object remove(Object name) { if (name instanceof String) { String fieldName = (String) name; FieldInfo fieldInfo = this.classInfo.getFieldInfo(fieldName); if (fieldInfo != null) { throw new UnsupportedOperationException(); } return this.unknownFields.remove(name); } return null; } @Override public Set> entrySet() { EntrySet entrySet = this.entrySet; if (entrySet == null) { entrySet = this.entrySet = new EntrySet(); } return entrySet; } @Override public GenericData clone() { try { @SuppressWarnings("unchecked") GenericData result = (GenericData) super.clone(); result.entrySet = null; DataUtil.cloneInternal(this, result); result.unknownFields = DataUtil.clone(this.unknownFields); return result; } catch (CloneNotSupportedException e) { throw new IllegalStateException(e); } } final class EntrySet extends AbstractSet> { @Override public Iterator> iterator() { return new EntryIterator(); } @Override public int size() { return GenericData.this.size(); } } final class EntryIterator implements Iterator> { private boolean startedUnknown; private final Iterator> unknownIterator; private final ReflectionMap.EntryIterator fieldIterator; EntryIterator() { this.fieldIterator = new ReflectionMap.EntryIterator(GenericData.this.classInfo, GenericData.this); this.unknownIterator = GenericData.this.unknownFields.entrySet().iterator(); } public boolean hasNext() { return !this.startedUnknown && this.fieldIterator.hasNext() || this.unknownIterator.hasNext(); } public Map.Entry next() { if (!this.startedUnknown) { ReflectionMap.EntryIterator fieldIterator = this.fieldIterator; if (fieldIterator.hasNext()) { return fieldIterator.next(); } this.startedUnknown = true; } return this.unknownIterator.next(); } public void remove() { if (this.startedUnknown) { this.unknownIterator.remove(); } throw new UnsupportedOperationException(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy