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 final ClassInfo classInfo = ClassInfo.of(getClass()); @Override public int size() { return classInfo.getKeyCount() + unknownFields.size(); } @Override public final Object get(Object name) { if (!(name instanceof String)) { return null; } String fieldName = (String) name; FieldInfo fieldInfo = classInfo.getFieldInfo(fieldName); if (fieldInfo != null) { return fieldInfo.getValue(this); } return unknownFields.get(fieldName); } @Override public final Object put(String name, Object value) { FieldInfo fieldInfo = classInfo.getFieldInfo(name); if (fieldInfo != null) { Object oldValue = fieldInfo.getValue(this); fieldInfo.setValue(this, value); return oldValue; } return 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 = classInfo.getFieldInfo(name); if (fieldInfo != null) { fieldInfo.setValue(this, value); return; } 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 = classInfo.getFieldInfo(fieldName); if (fieldInfo != null) { throw new UnsupportedOperationException(); } return 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(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() { fieldIterator = new ReflectionMap.EntryIterator(classInfo, GenericData.this); unknownIterator = unknownFields.entrySet().iterator(); } public boolean hasNext() { return !startedUnknown && fieldIterator.hasNext() || unknownIterator.hasNext(); } public Map.Entry next() { if (!startedUnknown) { ReflectionMap.EntryIterator fieldIterator = this.fieldIterator; if (fieldIterator.hasNext()) { return fieldIterator.next(); } startedUnknown = true; } return unknownIterator.next(); } public void remove() { if (startedUnknown) { unknownIterator.remove(); } throw new UnsupportedOperationException(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy