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

com.google.web.bindery.requestfactory.shared.impl.IdFactory Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 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.web.bindery.requestfactory.shared.impl;

import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ValueProxy;

import java.util.HashMap;
import java.util.Map;

/**
 * Handles common code for creating SimpleProxyIds.
 */
public abstract class IdFactory {
  /**
   * Maps ephemeral history tokens to an id object. This canonicalizing mapping
   * resolves the problem of EntityProxyIds hashcodes changing after persist.
   * Only ids that are created in the RequestFactory are stored here.
   */
  private final Map> ephemeralIds = new HashMap>();

  /**
   * Allocates an ephemeral proxy id. This object is only valid for the lifetime
   * of the RequestFactory.
   */
  public 

SimpleProxyId

allocateId(Class

clazz) { SimpleProxyId

toReturn = createId(clazz, ephemeralIds.size() + 1); ephemeralIds.put(getHistoryToken(toReturn), toReturn); return toReturn; } /** * Allocates a synthetic proxy id. This object is only valid for the lifetime * of a request. */ public

SimpleProxyId

allocateSyntheticId( Class

clazz, int syntheticId) { assert syntheticId > 0; SimpleProxyId

toReturn = createId(clazz, "%" + syntheticId); toReturn.setSyntheticId(syntheticId); return toReturn; } /** * A utility function to handle generic type conversion. This method will also * assert that {@code clazz} is actually an EntityProxy type. */ @SuppressWarnings("unchecked") public

Class

asEntityProxy( Class clazz) { assert isEntityType(clazz) : clazz.getName() + " is not an EntityProxy type"; return (Class

) clazz; } /** * A utility function to handle generic type conversion. This method will also * assert that {@code clazz} is actually a ValueProxy type. */ @SuppressWarnings("unchecked") public

Class

asValueProxy( Class clazz) { assert isValueType(clazz) : clazz.getName() + " is not a ValueProxy type"; return (Class

) clazz; } public

SimpleProxyId

getBaseProxyId( String historyToken) { assert !IdUtil.isSynthetic(historyToken) : "Synthetic id resolution" + " should be handled by AbstractRequestContext"; if (IdUtil.isPersisted(historyToken)) { return getId(IdUtil.getTypeToken(historyToken), IdUtil.getServerId(historyToken)); } if (IdUtil.isEphemeral(historyToken)) { @SuppressWarnings("unchecked") SimpleProxyId

toReturn = (SimpleProxyId

) ephemeralIds.get(historyToken); /* * This is tested in FindServiceTest.testFetchUnpersistedFutureId. In * order to get here, the user would have to get an unpersisted history * token and attempt to use it with a different RequestFactory instance. * This could occur if an ephemeral token were bookmarked. In this case, * we'll create a token, however it will never match anything. */ if (toReturn == null) { Class

clazz = checkTypeToken(IdUtil.getTypeToken(historyToken)); toReturn = createId(clazz, -1 * ephemeralIds.size()); ephemeralIds.put(historyToken, toReturn); } return toReturn; } throw new IllegalArgumentException(historyToken); } public String getHistoryToken(SimpleProxyId proxy) { SimpleProxyId id = (SimpleProxyId) proxy; String token = getTypeToken(proxy.getProxyClass()); if (id.isEphemeral()) { return IdUtil.ephemeralId(id.getClientId(), token); } else if (id.isSynthetic()) { return IdUtil.syntheticId(id.getSyntheticId(), token); } else { return IdUtil.persistedId(id.getServerId(), token); } } /** * Create or retrieve a SimpleProxyId. If both the serverId and clientId are * specified and the id is ephemeral, it will be updated with the server id. */ public

SimpleProxyId

getId(Class

clazz, String serverId, int clientId) { return getId(getTypeToken(clazz), serverId, clientId); } /** * Create or retrieve a SimpleProxyId. */ public

SimpleProxyId

getId(String typeToken, String serverId) { return getId(typeToken, serverId, 0); } /** * Create or retrieve a SimpleEntityProxyId. If both the serverId and clientId * are specified and the id is ephemeral, it will be updated with the server * id. */ public

SimpleProxyId

getId(String typeToken, String serverId, int clientId) { /* * If there's a clientId, that probably means we've just created a brand-new * EntityProxy or have just persisted something on the server. */ if (clientId > 0) { // Try a cache lookup for the ephemeral key String ephemeralKey = IdUtil.ephemeralId(clientId, typeToken); @SuppressWarnings("unchecked") SimpleProxyId

toReturn = (SimpleProxyId

) ephemeralIds.get(ephemeralKey); // Do we need to allocate an ephemeral id? if (toReturn == null) { Class

clazz = getTypeFromToken(typeToken); toReturn = createId(clazz, clientId); ephemeralIds.put(ephemeralKey, toReturn); } // If it's ephemeral, see if we have a serverId and save it if (toReturn.isEphemeral()) { // Sanity check assert toReturn.getProxyClass().equals(getTypeFromToken(typeToken)); if (serverId != null) { /* * Record the server id so a later "find" operation will have an equal * stableId. */ toReturn.setServerId(serverId); String serverKey = IdUtil.persistedId(serverId, typeToken); ephemeralIds.put(serverKey, toReturn); } } return toReturn; } // Should never get this far without a server id assert serverId != null : "serverId"; String serverKey = IdUtil.persistedId(serverId, typeToken); @SuppressWarnings("unchecked") SimpleProxyId

toReturn = (SimpleProxyId

) ephemeralIds.get(serverKey); if (toReturn != null) { // A cache hit for a locally-created object that has been persisted return toReturn; } /* * No existing id, so it was never an ephemeral id created by this * RequestFactory, so we don't need to record it. This should be the normal * case for read-dominated applications. */ Class

clazz = getTypeFromToken(typeToken); assert clazz != null : "No class literal for " + typeToken; return createId(clazz, serverId); } public abstract boolean isEntityType(Class clazz); public abstract boolean isValueType(Class clazz); protected abstract

Class

getTypeFromToken( String typeToken); protected abstract String getTypeToken(Class clazz); private

Class

checkTypeToken(String token) { @SuppressWarnings("unchecked") Class

clazz = (Class

) getTypeFromToken(token); if (clazz == null) { throw new IllegalArgumentException("Unknnown type"); } return clazz; } private

SimpleProxyId

createId(Class

clazz, int clientId) { SimpleProxyId

toReturn; if (isValueType(clazz)) { toReturn = new SimpleProxyId

(clazz, clientId); } else { @SuppressWarnings("unchecked") SimpleProxyId

temp = (SimpleProxyId

) new SimpleEntityProxyId( asEntityProxy(clazz), clientId); toReturn = (SimpleProxyId

) temp; } return toReturn; } private

SimpleProxyId

createId(Class

clazz, String serverId) { SimpleProxyId

toReturn; if (isValueType(clazz)) { toReturn = new SimpleProxyId

(clazz, serverId); } else { @SuppressWarnings("unchecked") SimpleProxyId

temp = (SimpleProxyId

) new SimpleEntityProxyId( asEntityProxy(clazz), serverId); toReturn = (SimpleProxyId

) temp; } return toReturn; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy