Following up on https://jira.springsource.org/browse/ROO-1276, here's the
proposed alternate design, separating the "keep history and places in sync" and
"map places to/from history tokens" concerns into a concrete PlaceHistoryHandler
class and a PlaceHistoryMapper interface whose implementation can be generated
based on annotations.
This patch superseeds http://gwt-code-reviews.appspot.com/824801/show and
integrates the changes from http://gwt-code-reviews.appspot.com/827801/show (if
it weren't the handler -> mapper renaming, they could have been kept separate).
Derived from http://gwt-code-reviews.appspot.com/845802, but without the
ActivityMapperGenerator bits.
Review by: rjrjr@google.com
Patch by: t.broyer@gmail.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8817 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/app/App.gwt.xml b/user/src/com/google/gwt/app/App.gwt.xml
index f894ed4..0487388 100644
--- a/user/src/com/google/gwt/app/App.gwt.xml
+++ b/user/src/com/google/gwt/app/App.gwt.xml
@@ -9,10 +9,7 @@
<generate-with class="com.google.gwt.app.rebind.EditorSupportGenerator">
<when-type-assignable class='com.google.gwt.app.client.EditorSupport'/>
</generate-with>
- <generate-with class="com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator">
- <when-type-assignable class="com.google.gwt.app.place.PlaceHistoryHandler"/>
- </generate-with>
- <generate-with class="com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator">
- <when-type-assignable class="com.google.gwt.app.place.PlaceHistoryHandlerWithFactory"/>
+ <generate-with class="com.google.gwt.app.rebind.PlaceHistoryMapperGenerator">
+ <when-type-assignable class="com.google.gwt.app.place.PlaceHistoryMapper"/>
</generate-with>
</module>
diff --git a/user/src/com/google/gwt/app/place/AbstractPlaceHistoryHandler.java b/user/src/com/google/gwt/app/place/AbstractPlaceHistoryHandler.java
deleted file mode 100644
index 5702467..0000000
--- a/user/src/com/google/gwt/app/place/AbstractPlaceHistoryHandler.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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.gwt.app.place;
-
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.History;
-
-import java.util.logging.Logger;
-
-/**
- * Abstract implementation of {@link PlaceHistoryHandler}.
- *
- * @param <F> the factory type
- */
-public abstract class AbstractPlaceHistoryHandler<F> implements
- PlaceHistoryHandlerWithFactory<F> {
- private static final Logger log = Logger.getLogger(AbstractPlaceHistoryHandler.class.getName());
-
- /**
- * Return value for
- * {@link AbstractPlaceHistoryHandler#getPrefixAndToken(Place)}.
- */
- public static class PrefixAndToken {
- public final String prefix;
- public final String token;
-
- public PrefixAndToken(String prefix, String token) {
- super();
- this.prefix = prefix;
- this.token = token;
- }
-
- @Override
- public String toString() {
- return prefix + ":" + token;
- }
- }
-
- /**
- * Isolates us from History, for testing.
- */
- protected interface Historian {
- HandlerRegistration addValueChangeHandler(
- ValueChangeHandler<String> valueChangeHandler);
-
- String getToken();
-
- void newItem(String token, boolean issueEvent);
- }
-
- private final Historian historian;
-
- protected F factory;
-
- protected PlaceController placeController;
-
- private Place defaultPlace = Place.NOWHERE;
-
- protected AbstractPlaceHistoryHandler() {
- this(new Historian() {
- public HandlerRegistration addValueChangeHandler(
- ValueChangeHandler<String> valueChangeHandler) {
- return History.addValueChangeHandler(valueChangeHandler);
- }
-
- public String getToken() {
- return History.getToken();
- }
-
- public void newItem(String token, boolean issueEvent) {
- History.newItem(token, issueEvent);
- }
- });
- }
-
- protected AbstractPlaceHistoryHandler(Historian historian) {
- this.historian = historian;
- }
-
- public void handleCurrentHistory() {
- handleHistoryToken(historian.getToken());
- }
-
- public HandlerRegistration register(PlaceController placeController,
- EventBus eventBus, Place defaultPlace) {
- assert factory != null : "No factory was set";
- this.placeController = placeController;
- this.defaultPlace = defaultPlace;
-
- final HandlerRegistration placeReg = eventBus.addHandler(
- PlaceChangeEvent.TYPE, new PlaceChangeEvent.Handler() {
- public void onPlaceChange(PlaceChangeEvent event) {
- Place newPlace = event.getNewPlace();
- historian.newItem(tokenForPlace(newPlace), false);
- }
- });
-
- final HandlerRegistration historyReg = historian.addValueChangeHandler(new ValueChangeHandler<String>() {
- public void onValueChange(ValueChangeEvent<String> event) {
- String token = event.getValue();
- handleHistoryToken(token);
- }
- });
-
- return new HandlerRegistration() {
- public void removeHandler() {
- AbstractPlaceHistoryHandler.this.defaultPlace = Place.NOWHERE;
- AbstractPlaceHistoryHandler.this.placeController = null;
- AbstractPlaceHistoryHandler.this.factory = null;
- placeReg.removeHandler();
- historyReg.removeHandler();
- }
- };
- }
-
- public void setFactory(F factory) {
- this.factory = factory;
- }
-
- /**
- * @param newPlace what needs tokenizing
- * @return the token, or null
- */
- protected abstract PrefixAndToken getPrefixAndToken(Place newPlace);
-
- /**
- * @param prefix the prefix found on the history token
- * @return the PlaceTokenizer registered with that token, or null
- */
- protected abstract PlaceTokenizer<?> getTokenizer(String prefix);
-
- /**
- * Visible for testing.
- */
- Logger log() {
- return log;
- }
-
- private void handleHistoryToken(String token) {
-
- Place newPlace = null;
-
- if ("".equals(token)) {
- newPlace = defaultPlace;
- }
-
- if (newPlace == null) {
- int colonAt = token.indexOf(':');
- if (colonAt > -1) {
- String initial = token.substring(0, colonAt);
- String rest = token.substring(colonAt + 1);
- PlaceTokenizer<?> tokenizer = getTokenizer(initial);
- if (tokenizer != null) {
- newPlace = tokenizer.getPlace(rest);
- }
- }
- }
-
- if (newPlace == null) {
- log().warning("Unrecognized history token: " + token);
- newPlace = defaultPlace;
- }
-
- placeController.goTo(newPlace);
- }
-
- private String tokenForPlace(Place newPlace) {
- if (defaultPlace.equals(newPlace)) {
- return "";
- }
-
- PrefixAndToken token = getPrefixAndToken(newPlace);
- if (token != null) {
- return token.toString();
- }
-
- log().warning("Unregistered place type : " + newPlace);
- return "";
- }
-
-}
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryHandler.java b/user/src/com/google/gwt/app/place/PlaceHistoryHandler.java
index e44e8a6..895d496 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryHandler.java
+++ b/user/src/com/google/gwt/app/place/PlaceHistoryHandler.java
@@ -15,27 +15,150 @@
*/
package com.google.gwt.app.place;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.History;
+
+import java.util.logging.Logger;
/**
- * Implemented by objects that monitor {@link PlaceChangeEvent}s and
- * {@link com.google.gwt.user.client.History} events and keep them in sync.
+ * Monitors {@link PlaceChangeEvent}s and {@link com.google.gwt.user.client.History} events and keep them in sync.
*/
-public interface PlaceHistoryHandler {
- /**
- * Sets the current place from current history token, e.g. in case of being
- * launched from a bookmark.
- */
- void handleCurrentHistory();
+public class PlaceHistoryHandler {
+ private static final Logger log = Logger.getLogger(PlaceHistoryHandler.class.getName());
/**
- * Registers this {@link PlaceHistoryHandler} with the event bus, and sets its
- * default place (where to go when there is no history token).
- *
- * @return registration object to deregister and reset the default place to
- * {@link Place#NOWHERE}.
+ * Default implementation of {@link Historian}, based on {@link History}.
*/
- HandlerRegistration register(PlaceController placeController, EventBus eventBus,
- Place defaultPlace);
+ public static class DefaultHistorian implements Historian {
+ public HandlerRegistration addValueChangeHandler(
+ ValueChangeHandler<String> valueChangeHandler) {
+ return History.addValueChangeHandler(valueChangeHandler);
+ }
+
+ public String getToken() {
+ return History.getToken();
+ }
+
+ public void newItem(String token, boolean issueEvent) {
+ History.newItem(token, issueEvent);
+ }
+ }
+
+ /**
+ * Optional delegate in charge of History related events. Provides nice
+ * isolation for unit testing, and allows pre- or post-processing of tokens.
+ */
+ public interface Historian {
+ HandlerRegistration addValueChangeHandler(
+ ValueChangeHandler<String> valueChangeHandler);
+
+ String getToken();
+
+ void newItem(String token, boolean issueEvent);
+ }
+
+ private final Historian historian;
+
+ private final PlaceHistoryMapper mapper;
+
+ private PlaceController placeController;
+
+ private Place defaultPlace = Place.NOWHERE;
+
+ /**
+ * Create a new PlaceHistoryHandler with a {@link DefaultHistorian}.
+ * The DefaultHistorian is created via a call to GWT.create(), so an
+ * alternative default implementation can be provided through
+ * <replace-with> rules in a gwt.xml file.
+ */
+ public PlaceHistoryHandler(PlaceHistoryMapper mapper) {
+ this(mapper, (Historian) GWT.create(DefaultHistorian.class));
+ }
+
+ /**
+ * Create a new PlaceHistoryHandler.
+ */
+ public PlaceHistoryHandler(PlaceHistoryMapper mapper, Historian historian) {
+ this.mapper = mapper;
+ this.historian = historian;
+ }
+
+ public void handleCurrentHistory() {
+ handleHistoryToken(historian.getToken());
+ }
+
+ public HandlerRegistration register(PlaceController placeController,
+ EventBus eventBus, Place defaultPlace) {
+ this.placeController = placeController;
+ this.defaultPlace = defaultPlace;
+
+ final HandlerRegistration placeReg = eventBus.addHandler(
+ PlaceChangeEvent.TYPE, new PlaceChangeEvent.Handler() {
+ public void onPlaceChange(PlaceChangeEvent event) {
+ Place newPlace = event.getNewPlace();
+ historian.newItem(tokenForPlace(newPlace), false);
+ }
+ });
+
+ final HandlerRegistration historyReg = historian.addValueChangeHandler(new ValueChangeHandler<String>() {
+ public void onValueChange(ValueChangeEvent<String> event) {
+ String token = event.getValue();
+ handleHistoryToken(token);
+ }
+ });
+
+ return new HandlerRegistration() {
+ public void removeHandler() {
+ PlaceHistoryHandler.this.defaultPlace = Place.NOWHERE;
+ PlaceHistoryHandler.this.placeController = null;
+ placeReg.removeHandler();
+ historyReg.removeHandler();
+ }
+ };
+ }
+
+ /**
+ * Visible for testing.
+ */
+ Logger log() {
+ return log;
+ }
+
+ private void handleHistoryToken(String token) {
+
+ Place newPlace = null;
+
+ if ("".equals(token)) {
+ newPlace = defaultPlace;
+ }
+
+ if (newPlace == null) {
+ newPlace = mapper.getPlace(token);
+ }
+
+ if (newPlace == null) {
+ log().warning("Unrecognized history token: " + token);
+ newPlace = defaultPlace;
+ }
+
+ placeController.goTo(newPlace);
+ }
+
+ private String tokenForPlace(Place newPlace) {
+ if (defaultPlace.equals(newPlace)) {
+ return "";
+ }
+
+ String token = mapper.getToken(newPlace);
+ if (token != null) {
+ return token;
+ }
+
+ log().warning("Place not mapped to a token: " + newPlace);
+ return "";
+ }
}
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java b/user/src/com/google/gwt/app/place/PlaceHistoryMapper.java
similarity index 63%
copy from user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java
copy to user/src/com/google/gwt/app/place/PlaceHistoryMapper.java
index cdc38ab..59a27a1 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java
+++ b/user/src/com/google/gwt/app/place/PlaceHistoryMapper.java
@@ -16,12 +16,17 @@
package com.google.gwt.app.place;
/**
- * A PlaceHistoryHandler that can get its {@link PlaceTokenizer} instances from
- * a factory.
- *
- * @param <F> factory type
+ * <p>
+ * <span style="color:red">Experimental API: This class is still under rapid
+ * development, and is very likely to be deleted. Use it at your own risk.
+ * </span>
+ * </p>
+ * Maps {@link Place}s to/from tokens, used to configure a
+ * {@link PlaceHistoryHandler}.
*/
-public interface PlaceHistoryHandlerWithFactory<F> extends PlaceHistoryHandler {
+public interface PlaceHistoryMapper {
- void setFactory(F factory);
+ Place getPlace(String token);
+
+ String getToken(Place place);
}
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java b/user/src/com/google/gwt/app/place/PlaceHistoryMapperWithFactory.java
similarity index 81%
rename from user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java
rename to user/src/com/google/gwt/app/place/PlaceHistoryMapperWithFactory.java
index cdc38ab..22c0b02 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java
+++ b/user/src/com/google/gwt/app/place/PlaceHistoryMapperWithFactory.java
@@ -16,12 +16,12 @@
package com.google.gwt.app.place;
/**
- * A PlaceHistoryHandler that can get its {@link PlaceTokenizer} instances from
+ * A PlaceHistoryMapper that can get its {@link PlaceTokenizer} instances from
* a factory.
*
* @param <F> factory type
*/
-public interface PlaceHistoryHandlerWithFactory<F> extends PlaceHistoryHandler {
+public interface PlaceHistoryMapperWithFactory<F> extends PlaceHistoryMapper {
void setFactory(F factory);
}
diff --git a/user/src/com/google/gwt/app/place/Prefix.java b/user/src/com/google/gwt/app/place/Prefix.java
index 4c9808c..ce68c3b 100644
--- a/user/src/com/google/gwt/app/place/Prefix.java
+++ b/user/src/com/google/gwt/app/place/Prefix.java
@@ -24,7 +24,7 @@
* Indicates the prefix to use when the token written by
* {@link PlaceTokenizer#getToken(Place)} is written to
* {@link com.google.gwt.user.client.History#newItem}.
- * {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator} looks
+ * {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator} looks
* for this annotation on the factory methods that return a tokenizer, and on
* the tokenizer types themselves.
*/
diff --git a/user/src/com/google/gwt/app/place/WithTokenizers.java b/user/src/com/google/gwt/app/place/WithTokenizers.java
index df64d75..d592055 100644
--- a/user/src/com/google/gwt/app/place/WithTokenizers.java
+++ b/user/src/com/google/gwt/app/place/WithTokenizers.java
@@ -22,8 +22,8 @@
/**
* Indicates {@link PlaceTokenizer} types used by an implementation of
- * {@link PlaceHistoryHandler} generated by
- * {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * {@link PlaceHistoryMapper} generated by
+ * {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/user/src/com/google/gwt/app/place/impl/AbstractPlaceHistoryMapper.java b/user/src/com/google/gwt/app/place/impl/AbstractPlaceHistoryMapper.java
new file mode 100644
index 0000000..0c9794a
--- /dev/null
+++ b/user/src/com/google/gwt/app/place/impl/AbstractPlaceHistoryMapper.java
@@ -0,0 +1,88 @@
+/*
+ * 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.gwt.app.place.impl;
+
+import com.google.gwt.app.place.Place;
+import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
+import com.google.gwt.app.place.PlaceTokenizer;
+
+/**
+ * Abstract implementation of {@link PlaceHistoryMapper}.
+ *
+ * @param <F> factory type
+ */
+public abstract class AbstractPlaceHistoryMapper<F> implements
+ PlaceHistoryMapperWithFactory<F> {
+
+ /**
+ * Return value for
+ * {@link AbstractPlaceHistoryMapper#getPrefixAndToken(Place)}.
+ */
+ public static class PrefixAndToken {
+ public final String prefix;
+ public final String token;
+
+ public PrefixAndToken(String prefix, String token) {
+ assert prefix != null && !prefix.contains(":");
+ this.prefix = prefix;
+ this.token = token;
+ }
+
+ @Override
+ public String toString() {
+ return prefix.isEmpty() ? token : prefix + ":" + token;
+ }
+ }
+
+ protected F factory;
+
+ public Place getPlace(String token) {
+ int colonAt = token.indexOf(':');
+ if (colonAt > 0) {
+ String initial = token.substring(0, colonAt);
+ String rest = token.substring(colonAt + 1);
+ PlaceTokenizer<?> tokenizer = getTokenizer(initial);
+ if (tokenizer != null) {
+ return tokenizer.getPlace(rest);
+ }
+ }
+ return null;
+ }
+
+ public String getToken(Place place) {
+ PrefixAndToken token = getPrefixAndToken(place);
+ if (token != null) {
+ return token.toString();
+ }
+ return null;
+ }
+
+ public void setFactory(F factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * @param newPlace what needs tokenizing
+ * @return the token, or null
+ */
+ protected abstract PrefixAndToken getPrefixAndToken(Place newPlace);
+
+ /**
+ * @param prefix the prefix found on the history token
+ * @return the PlaceTokenizer registered with that token, or null
+ */
+ protected abstract PlaceTokenizer<?> getTokenizer(String prefix);
+}
diff --git a/user/src/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparator.java b/user/src/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparator.java
new file mode 100644
index 0000000..477de65
--- /dev/null
+++ b/user/src/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparator.java
@@ -0,0 +1,40 @@
+/*
+ * 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.gwt.app.rebind;
+
+import com.google.gwt.core.ext.typeinfo.JClassType;
+
+import java.util.Comparator;
+
+/**
+ * Sorts types from most derived to least derived, falling back to alphabetical
+ * sorting.
+ */
+public class MostToLeastDerivedPlaceTypeComparator implements
+ Comparator<JClassType> {
+ public int compare(JClassType o1, JClassType o2) {
+ if (o1.equals(o2)) {
+ return 0;
+ }
+ if (o1.isAssignableFrom(o2)) {
+ return 1;
+ }
+ if (o1.isAssignableTo(o2)) {
+ return -1;
+ }
+ return o1.getQualifiedSourceName().compareTo(o2.getQualifiedSourceName());
+ }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java b/user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java
index 7428fdc..62cdd00 100644
--- a/user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java
+++ b/user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java
@@ -15,11 +15,10 @@
*/
package com.google.gwt.app.rebind;
-import com.google.gwt.app.place.PlaceHistoryHandlerWithFactory;
+import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
import com.google.gwt.app.place.PlaceTokenizer;
import com.google.gwt.app.place.Prefix;
import com.google.gwt.app.place.WithTokenizers;
-import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
@@ -33,23 +32,20 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.Map.Entry;
+import java.util.TreeMap;
class PlaceHistoryGeneratorContext {
static PlaceHistoryGeneratorContext create(TreeLogger logger,
- GeneratorContext generatorContext, String interfaceName)
+ TypeOracle typeOracle, String interfaceName)
throws UnableToCompleteException {
- TypeOracle typeOracle = generatorContext.getTypeOracle();
JClassType stringType = requireType(typeOracle, String.class);
JClassType placeTokenizerType = requireType(typeOracle,
PlaceTokenizer.class);
- JClassType placeHistoryHandlerWithFactoryType = requireType(typeOracle,
- PlaceHistoryHandlerWithFactory.class);
+ JClassType placeHistoryMapperWithFactoryType = requireType(typeOracle,
+ PlaceHistoryMapperWithFactory.class);
JClassType factoryType;
@@ -66,26 +62,25 @@
throw new UnableToCompleteException();
}
- factoryType = findFactoryType(placeHistoryHandlerWithFactoryType,
+ factoryType = findFactoryType(placeHistoryMapperWithFactoryType,
interfaceType);
String implName = interfaceType.getName().replace(".", "_") + "Impl";
- return new PlaceHistoryGeneratorContext(logger, generatorContext,
- interfaceType, factoryType, stringType, placeTokenizerType,
- placeHistoryHandlerWithFactoryType,
+ return new PlaceHistoryGeneratorContext(logger, typeOracle, interfaceType,
+ factoryType, stringType, placeTokenizerType,
interfaceType.getPackage().getName(), implName);
}
private static JClassType findFactoryType(
- JClassType placeHistoryHandlerWithFactoryType, JClassType interfaceType) {
+ JClassType placeHistoryMapperWithFactoryType, JClassType interfaceType) {
JClassType superInterfaces[] = interfaceType.getImplementedInterfaces();
for (JClassType superInterface : superInterfaces) {
JParameterizedType parameterizedType = superInterface.isParameterized();
if (parameterizedType != null
&& parameterizedType.getBaseType().equals(
- placeHistoryHandlerWithFactoryType)) {
+ placeHistoryMapperWithFactoryType)) {
return parameterizedType.getTypeArgs()[0];
}
}
@@ -104,10 +99,9 @@
final JClassType stringType;
final JClassType placeTokenizerType;
- final JClassType placeHistoryHandlerType;
final TreeLogger logger;
- final GeneratorContext generatorContext;
+ final TypeOracle typeOracle;
final JClassType interfaceType;
final JClassType factoryType;
@@ -116,79 +110,115 @@
final String packageName;
/**
- * All factory getters that can provide tokenizers, by prefix.
+ * All tokenizers, either as a {@link JMethod} for factory getters or as a
+ * {@link JClassType} for types that must be GWT.create()d, by prefix.
*/
- private LinkedHashMap<String, JMethod> tokenizerGetters;
+ private HashMap<String, Object> tokenizers;
/**
- * All tokenizer types that must be GWT.create()d, by prefix.
+ * All place types and the prefix of their associated tokenizer, ordered from
+ * most-derived to least-derived type (and falling back to the natural
+ * ordering of their names).
*/
- private LinkedHashMap<String, JClassType> tokenizersWithNoGetters;
+ private TreeMap<JClassType, String> placeTypes = new TreeMap<JClassType, String>(
+ new MostToLeastDerivedPlaceTypeComparator());
- /**
- * Cache of all tokenizer types, union of the entries in tokenizerGetters and
- * tokenizersWithNoGetters.
- */
- private LinkedHashMap<String, JClassType> tokenizerTypes;
-
- PlaceHistoryGeneratorContext(TreeLogger logger,
- GeneratorContext generatorContext, JClassType interfaceType,
- JClassType factoryType, JClassType stringType,
- JClassType placeTokenizerType, JClassType placeHistoryHandlerType,
- String packageName, String implName) {
+ PlaceHistoryGeneratorContext(TreeLogger logger, TypeOracle typeOracle,
+ JClassType interfaceType, JClassType factoryType, JClassType stringType,
+ JClassType placeTokenizerType, String packageName, String implName) {
this.logger = logger;
- this.generatorContext = generatorContext;
+ this.typeOracle = typeOracle;
this.interfaceType = interfaceType;
this.factoryType = factoryType;
this.stringType = stringType;
this.placeTokenizerType = placeTokenizerType;
- this.placeHistoryHandlerType = placeHistoryHandlerType;
this.packageName = packageName;
this.implName = implName;
}
- public JClassType getPlaceType(String prefix)
+ public Set<JClassType> getPlaceTypes() throws UnableToCompleteException {
+ ensureInitialized();
+ return placeTypes.keySet();
+ }
+
+ public String getPrefix(JClassType placeType)
throws UnableToCompleteException {
- return getPlaceTypeForTokenizerType(getTokenizerType(prefix));
+ ensureInitialized();
+ return placeTypes.get(placeType);
}
public Set<String> getPrefixes() throws UnableToCompleteException {
- return getTokenizerTypes().keySet();
+ ensureInitialized();
+ return tokenizers.keySet();
}
public JMethod getTokenizerGetter(String prefix)
throws UnableToCompleteException {
- return getTokenizerGetters().get(prefix);
+ ensureInitialized();
+ Object tokenizerGetter = tokenizers.get(prefix);
+ if (tokenizerGetter instanceof JMethod) {
+ return (JMethod) tokenizerGetter;
+ }
+ return null;
}
public JClassType getTokenizerType(String prefix)
throws UnableToCompleteException {
-
- JMethod getter = getTokenizerGetters().get(prefix);
- if (getter != null) {
- return getter.getReturnType().isClassOrInterface();
+ ensureInitialized();
+ Object tokenizerType = tokenizers.get(prefix);
+ if (tokenizerType instanceof JClassType) {
+ return (JClassType) tokenizerType;
}
-
- return getTokenizersWihoutGetters().get(prefix);
+ return null;
}
- public Map<String, JClassType> getTokenizerTypes()
- throws UnableToCompleteException {
- if (tokenizerTypes == null) {
- tokenizerTypes = new LinkedHashMap<String, JClassType>();
- for (Entry<String, JMethod> entry : getTokenizerGetters().entrySet()) {
- tokenizerTypes.put(entry.getKey(),
- entry.getValue().getReturnType().isClassOrInterface());
- }
- for (Entry<String, JClassType> entry : getTokenizersWihoutGetters().entrySet()) {
- tokenizerTypes.put(entry.getKey(), entry.getValue());
- }
+ void ensureInitialized() throws UnableToCompleteException {
+ if (tokenizers == null) {
+ assert placeTypes.isEmpty();
+ tokenizers = new HashMap<String, Object>();
+ initTokenizerGetters();
+ initTokenizersWithoutGetters();
}
- return tokenizerTypes;
}
- public boolean hasNonFactoryTokenizer() throws UnableToCompleteException {
- return !getTokenizersWihoutGetters().isEmpty();
+ private void addPlaceTokenizer(Object tokenizerClassOrGetter, String prefix,
+ JClassType tokenizerType) throws UnableToCompleteException {
+ if (prefix.contains(":")) {
+ logger.log(TreeLogger.ERROR, String.format(
+ "Found place prefix \"%s\" containing separator char \":\", on %s",
+ prefix, getLogMessage(tokenizerClassOrGetter)));
+ throw new UnableToCompleteException();
+ }
+ if (tokenizers.containsKey(prefix)) {
+ logger.log(TreeLogger.ERROR, String.format(
+ "Found duplicate place prefix \"%s\" on %s, already seen on %s",
+ prefix, getLogMessage(tokenizerClassOrGetter),
+ getLogMessage(tokenizers.get(prefix))));
+ throw new UnableToCompleteException();
+ }
+ JClassType placeType = getPlaceTypeForTokenizerType(tokenizerType);
+ if (placeTypes.containsKey(placeType)) {
+ logger.log(
+ TreeLogger.ERROR,
+ String.format(
+ "Found duplicate tokenizer's place type \"%s\" on %s, already seen on %s",
+ placeType.getQualifiedSourceName(),
+ getLogMessage(tokenizerClassOrGetter),
+ getLogMessage(tokenizers.get(placeTypes.get(placeType)))));
+ throw new UnableToCompleteException();
+ }
+ tokenizers.put(prefix, tokenizerClassOrGetter);
+ placeTypes.put(placeType, prefix);
+ }
+
+ private String getLogMessage(Object methodOrClass) {
+ if (methodOrClass instanceof JMethod) {
+ JMethod method = (JMethod) methodOrClass;
+ return method.getEnclosingType().getQualifiedSourceName() + "#"
+ + method.getName() + "()";
+ }
+ JClassType classType = (JClassType) methodOrClass;
+ return classType.getQualifiedSourceName();
}
private JClassType getPlaceTypeForTokenizerType(JClassType tokenizerType)
@@ -235,29 +265,37 @@
return getPlaceTypeForTokenizerType(returnType).getName();
}
- private Map<String, JMethod> getTokenizerGetters()
- throws UnableToCompleteException {
- if (factoryType == null) {
- return Collections.emptyMap();
+ private Set<JClassType> getWithTokenizerEntries() {
+ WithTokenizers annotation = interfaceType.getAnnotation(WithTokenizers.class);
+ if (annotation == null) {
+ return Collections.emptySet();
}
- if (tokenizerGetters == null) {
- tokenizerGetters = new LinkedHashMap<String, JMethod>();
-
- /* Gets inherited methods, but not final ones */
- JMethod[] overridableMethods = factoryType.getOverridableMethods();
- /* So we pick up the finals here */
- JMethod[] methods = factoryType.getMethods();
-
- LinkedHashSet<JMethod> allMethods = new LinkedHashSet<JMethod>();
- allMethods.addAll(Arrays.asList(overridableMethods));
- for (JMethod method : methods) {
- if (method.isPublic()) {
- allMethods.add(method);
- }
+ LinkedHashSet<JClassType> rtn = new LinkedHashSet<JClassType>();
+ for (Class<? extends PlaceTokenizer<?>> tokenizerClass : annotation.value()) {
+ JClassType tokenizerType = typeOracle.findType(tokenizerClass.getCanonicalName());
+ if (tokenizerType == null) {
+ logger.log(TreeLogger.ERROR, String.format(
+ "Error processing @%s, cannot find type %s",
+ WithTokenizers.class.getSimpleName(),
+ tokenizerClass.getCanonicalName()));
}
+ rtn.add(tokenizerType);
+ }
- for (JMethod method : allMethods) {
+ return rtn;
+ }
+
+ private void initTokenizerGetters() throws UnableToCompleteException {
+ if (factoryType != null) {
+
+ // TODO: include non-public methods that are nevertheless accessible
+ // to the interface (package-scoped);
+ // Add a isCallable(JClassType) method to JAbstractMethod?
+ for (JMethod method : factoryType.getInheritableMethods()) {
+ if (!method.isPublic()) {
+ continue;
+ }
if (method.getParameters().length > 0) {
continue;
}
@@ -272,56 +310,17 @@
continue;
}
- String prefix = getPrefixForTokenizerGetter(method);
- if (tokenizerGetters.containsKey(prefix)) {
- logger.log(TreeLogger.ERROR, String.format(
- "Found duplicate place prefix \"%s\" in factory type %s, "
- + "used by both %s and %s", prefix,
- factoryType.getQualifiedSourceName(),
- tokenizerGetters.get(prefix).getName(), method.getName()));
- throw new UnableToCompleteException();
- }
- tokenizerGetters.put(prefix, method);
+ addPlaceTokenizer(method, getPrefixForTokenizerGetter(method),
+ method.getReturnType().isClassOrInterface());
}
}
-
- return tokenizerGetters;
}
- private HashMap<String, JClassType> getTokenizersWihoutGetters()
- throws UnableToCompleteException {
- if (tokenizersWithNoGetters == null) {
- tokenizersWithNoGetters = new LinkedHashMap<String, JClassType>();
-
- for (JClassType tokenizerType : getWithTokenizerEntries()) {
- tokenizersWithNoGetters.put(getPrefixForTokenizerType(tokenizerType),
- tokenizerType);
- }
+ private void initTokenizersWithoutGetters() throws UnableToCompleteException {
+ for (JClassType tokenizerType : getWithTokenizerEntries()) {
+ addPlaceTokenizer(tokenizerType,
+ getPrefixForTokenizerType(tokenizerType), tokenizerType);
}
-
- return tokenizersWithNoGetters;
- }
-
- private Set<JClassType> getWithTokenizerEntries() {
- WithTokenizers annotation = interfaceType.getAnnotation(WithTokenizers.class);
- if (annotation == null) {
- return Collections.emptySet();
- }
-
- LinkedHashSet<JClassType> rtn = new LinkedHashSet<JClassType>();
- for (Class<? extends PlaceTokenizer<?>> tokenizerClass : annotation.value()) {
- JClassType tokenizerType = generatorContext.getTypeOracle().findType(
- tokenizerClass.getCanonicalName());
- if (tokenizerType == null) {
- logger.log(TreeLogger.ERROR, String.format(
- "Error processing @%s, cannot find type %s",
- WithTokenizers.class.getSimpleName(),
- tokenizerClass.getCanonicalName()));
- }
- rtn.add(tokenizerType);
- }
-
- return rtn;
}
private JClassType placeTypeForInterfaces(Collection<JClassType> interfaces) {
diff --git a/user/src/com/google/gwt/app/rebind/PlaceHistoryHandlerGenerator.java b/user/src/com/google/gwt/app/rebind/PlaceHistoryMapperGenerator.java
similarity index 73%
rename from user/src/com/google/gwt/app/rebind/PlaceHistoryHandlerGenerator.java
rename to user/src/com/google/gwt/app/rebind/PlaceHistoryMapperGenerator.java
index 540cc3e..8c04432 100644
--- a/user/src/com/google/gwt/app/rebind/PlaceHistoryHandlerGenerator.java
+++ b/user/src/com/google/gwt/app/rebind/PlaceHistoryMapperGenerator.java
@@ -15,10 +15,10 @@
*/
package com.google.gwt.app.rebind;
-import com.google.gwt.app.place.AbstractPlaceHistoryHandler;
import com.google.gwt.app.place.Place;
import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.AbstractPlaceHistoryHandler.PrefixAndToken;
+import com.google.gwt.app.place.impl.AbstractPlaceHistoryMapper;
+import com.google.gwt.app.place.impl.AbstractPlaceHistoryMapper.PrefixAndToken;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
@@ -30,7 +30,6 @@
import com.google.gwt.user.rebind.SourceWriter;
import java.io.PrintWriter;
-import java.util.Map.Entry;
/**
* <p>
@@ -39,29 +38,29 @@
* </span>
* </p>
* Generates implementations of
- * {@link com.google.gwt.app.place.PlaceHistoryHandler PlaceHistoryHandler}.
+ * {@link com.google.gwt.app.place.PlaceHistoryMapper PlaceHistoryMapper}.
*/
-public class PlaceHistoryHandlerGenerator extends Generator {
+public class PlaceHistoryMapperGenerator extends Generator {
private PlaceHistoryGeneratorContext context;
@Override
public String generate(TreeLogger logger, GeneratorContext generatorContext,
String interfaceName) throws UnableToCompleteException {
- context = PlaceHistoryGeneratorContext.create(logger, generatorContext,
- interfaceName);
+ context = PlaceHistoryGeneratorContext.create(logger,
+ generatorContext.getTypeOracle(), interfaceName);
PrintWriter out = generatorContext.tryCreate(logger, context.packageName,
context.implName);
if (out != null) {
- generateOnce(context, out);
+ generateOnce(generatorContext, context, out);
}
return context.packageName + "." + context.implName;
}
- private void generateOnce(PlaceHistoryGeneratorContext context,
+ private void generateOnce(GeneratorContext generatorContext, PlaceHistoryGeneratorContext context,
PrintWriter out) throws UnableToCompleteException {
TreeLogger logger = context.logger.branch(TreeLogger.DEBUG, String.format(
@@ -70,15 +69,15 @@
context.packageName, context.implName);
String superClassName = String.format("%s<%s>",
- AbstractPlaceHistoryHandler.class.getSimpleName(),
+ AbstractPlaceHistoryMapper.class.getSimpleName(),
context.factoryType == null ? "Void" : context.factoryType.getName());
f.setSuperclass(superClassName);
f.addImplementedInterface(context.interfaceType.getName());
-
- f.addImport(AbstractPlaceHistoryHandler.class.getName());
+
+ f.addImport(AbstractPlaceHistoryMapper.class.getName());
f.addImport(context.interfaceType.getQualifiedSourceName());
- f.addImport(AbstractPlaceHistoryHandler.class.getCanonicalName());
+ f.addImport(AbstractPlaceHistoryMapper.class.getCanonicalName());
if (context.factoryType != null) {
f.addImport(context.factoryType.getQualifiedSourceName());
}
@@ -87,16 +86,9 @@
f.addImport(PlaceTokenizer.class.getCanonicalName());
f.addImport(PrefixAndToken.class.getCanonicalName());
- for (Entry<String, JClassType> entry : context.getTokenizerTypes().entrySet()) {
- f.addImport(entry.getValue().getQualifiedSourceName());
- f.addImport(context.getPlaceType(entry.getKey()).getQualifiedSourceName());
- }
+ f.addImport(GWT.class.getCanonicalName());
- if (context.hasNonFactoryTokenizer()) {
- f.addImport(GWT.class.getCanonicalName());
- }
-
- SourceWriter sw = f.createSourceWriter(context.generatorContext, out);
+ SourceWriter sw = f.createSourceWriter(generatorContext, out);
sw.println();
writeGetPrefixAndToken(context, sw);
@@ -107,15 +99,16 @@
sw.outdent();
sw.println("}");
- context.generatorContext.commit(logger, out);
+ generatorContext.commit(logger, out);
}
private void writeGetPrefixAndToken(PlaceHistoryGeneratorContext context,
SourceWriter sw) throws UnableToCompleteException {
sw.println("protected PrefixAndToken getPrefixAndToken(Place newPlace) {");
sw.indent();
- for (String prefix : context.getPrefixes()) {
- String placeTypeName = context.getPlaceType(prefix).getName();
+ for (JClassType placeType : context.getPlaceTypes()) {
+ String placeTypeName = placeType.getQualifiedSourceName();
+ String prefix = context.getPrefix(placeType);
sw.println("if (newPlace instanceof " + placeTypeName + ") {");
sw.indent();
@@ -124,13 +117,14 @@
JMethod getter = context.getTokenizerGetter(prefix);
if (getter != null) {
sw.println(String.format("return new PrefixAndToken(\"%s\", "
- + "factory.%s().getToken(place));", prefix, getter.getName()));
+ + "factory.%s().getToken(place));", escape(prefix),
+ getter.getName()));
} else {
sw.println(String.format(
"PlaceTokenizer<%s> t = GWT.create(%s.class);", placeTypeName,
- context.getTokenizerType(prefix).getName()));
+ context.getTokenizerType(prefix).getQualifiedSourceName()));
sw.println(String.format("return new PrefixAndToken(\"%s\", "
- + "t.getToken((%s) place));", prefix, placeTypeName));
+ + "t.getToken((%s) place));", escape(prefix), placeTypeName));
}
sw.outdent();
@@ -150,14 +144,14 @@
for (String prefix : context.getPrefixes()) {
JMethod getter = context.getTokenizerGetter(prefix);
- sw.println("if (\"" + prefix + "\".equals(prefix)) {");
+ sw.println("if (\"" + escape(prefix) + "\".equals(prefix)) {");
sw.indent();
if (getter != null) {
sw.println("return factory." + getter.getName() + "();");
} else {
sw.println(String.format("return GWT.create(%s.class);",
- context.getTokenizerType(prefix).getName()));
+ context.getTokenizerType(prefix).getQualifiedSourceName()));
}
sw.outdent();
diff --git a/user/test/com/google/gwt/app/AppJreSuite.java b/user/test/com/google/gwt/app/AppJreSuite.java
index 4c824d6..5708bf5 100644
--- a/user/test/com/google/gwt/app/AppJreSuite.java
+++ b/user/test/com/google/gwt/app/AppJreSuite.java
@@ -16,9 +16,10 @@
package com.google.gwt.app;
import com.google.gwt.app.place.ActivityManagerTest;
-import com.google.gwt.app.place.AbstractPlaceHistoryHandlerTest;
import com.google.gwt.app.place.PlaceChangeRequestEventTest;
import com.google.gwt.app.place.PlaceControllerTest;
+import com.google.gwt.app.place.PlaceHistoryHandlerTest;
+import com.google.gwt.app.rebind.PlaceHistoryGeneratorContextTest;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -30,9 +31,10 @@
public static Test suite() {
TestSuite suite = new TestSuite("app package tests that require the JRE");
suite.addTestSuite(ActivityManagerTest.class);
- suite.addTestSuite(AbstractPlaceHistoryHandlerTest.class);
suite.addTestSuite(PlaceControllerTest.class);
suite.addTestSuite(PlaceChangeRequestEventTest.class);
+ suite.addTestSuite(PlaceHistoryGeneratorContextTest.class);
+ suite.addTestSuite(PlaceHistoryHandlerTest.class);
return suite;
}
}
diff --git a/user/test/com/google/gwt/app/AppSuite.gwt.xml b/user/test/com/google/gwt/app/AppSuite.gwt.xml
deleted file mode 100644
index 0a3af91..0000000
--- a/user/test/com/google/gwt/app/AppSuite.gwt.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.0.1//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.0.1/distro-source/core/src/gwt-module.dtd">
-<!--
- 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.
--->
-<module>
- <inherits name='com.google.gwt.app.App'/>
- <inherits name='com.google.gwt.junit.JUnit'/>
- <source path='place'/>
-</module>
diff --git a/user/test/com/google/gwt/app/AppSuite.java b/user/test/com/google/gwt/app/AppSuite.java
index 06f1997..af744ed 100644
--- a/user/test/com/google/gwt/app/AppSuite.java
+++ b/user/test/com/google/gwt/app/AppSuite.java
@@ -15,7 +15,8 @@
*/
package com.google.gwt.app;
-import com.google.gwt.app.place.PlaceHistoryHandlerGeneratorTest;
+import com.google.gwt.app.place.impl.PlaceHistoryMapperGeneratorTest;
+import com.google.gwt.junit.tools.GWTTestSuite;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -25,8 +26,8 @@
*/
public class AppSuite {
public static Test suite() {
- TestSuite suite = new TestSuite("app package tests that require GWT");
- suite.addTestSuite(PlaceHistoryHandlerGeneratorTest.class);
+ TestSuite suite = new GWTTestSuite("app package tests that require GWT");
+ suite.addTestSuite(PlaceHistoryMapperGeneratorTest.class);
return suite;
}
}
diff --git a/user/test/com/google/gwt/app/place/AbstractPlaceHistoryHandlerTest.java b/user/test/com/google/gwt/app/place/AbstractPlaceHistoryHandlerTest.java
deleted file mode 100644
index 93c6ef4..0000000
--- a/user/test/com/google/gwt/app/place/AbstractPlaceHistoryHandlerTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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.gwt.app.place;
-
-import com.google.gwt.app.place.testplaces.Place1;
-import com.google.gwt.app.place.testplaces.Place2;
-import com.google.gwt.app.place.testplaces.Tokenizer2;
-import com.google.gwt.app.place.testplaces.TokenizerFactory;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.event.shared.SimpleEventBus;
-
-import junit.framework.TestCase;
-
-import java.util.logging.Logger;
-
-/**
- * Eponymous unit test.
- */
-public class AbstractPlaceHistoryHandlerTest extends TestCase {
- private static class MockHistorian implements
- AbstractPlaceHistoryHandler.Historian {
- final HandlerRegistration registration = new Registration();
-
- ValueChangeHandler<String> handler;
- String token = "";
-
- public HandlerRegistration addValueChangeHandler(
- ValueChangeHandler<String> valueChangeHandler) {
- this.handler = valueChangeHandler;
- return registration;
- }
-
- public String getToken() {
- return token;
- }
-
- public void newItem(String token, boolean issueEvent) {
- assertFalse(issueEvent);
- this.token = token;
- }
-
- public void postToken(String string) {
- handler.onValueChange(new ValueChangeEvent<String>(string) {
- });
- }
- }
-
- private static class Registration implements HandlerRegistration {
- public void removeHandler() {
- throw new UnsupportedOperationException("Auto-generated method stub");
- }
- }
-
- private class Subject extends AbstractPlaceHistoryHandler<TokenizerFactory> {
-
- Subject(Historian historian) {
- super(historian);
- }
-
- @Override
- protected PrefixAndToken getPrefixAndToken(Place newPlace) {
- if (newPlace instanceof Place1) {
- return new PrefixAndToken(PREFIX1, factory.getTokenizer1().getToken(
- (Place1) newPlace));
- }
- if (newPlace instanceof Place2) {
- return new PrefixAndToken(PREFIX2,
- new Tokenizer2().getToken((Place2) newPlace));
- }
-
- return null;
- }
-
- @Override
- protected PlaceTokenizer<?> getTokenizer(String prefix) {
- if (PREFIX1.equals(prefix)) {
- return factory.getTokenizer1();
- }
- if (PREFIX2.equals(prefix)) {
- return new Tokenizer2();
- }
-
- return null;
- }
-
- TokenizerFactory getFactory() {
- return factory;
- }
-
- @Override
- Logger log() {
- return deadLogger;
- }
- }
-
- private static final String PREFIX1 = "t1";
-
- private static final String PREFIX2 = "token2";
-
- Logger deadLogger = new Logger("shut up", null) {
- };
-
- EventBus eventBus = new SimpleEventBus();
-
- PlaceController placeController = new PlaceController(eventBus,
- new MockPlaceControllerDelegate()) {
- @Override
- Logger log() {
- return deadLogger;
- }
- };
-
- MockHistorian historian = new MockHistorian();
-
- Subject subject = new Subject(historian);
- Place1 place1 = new Place1("able");
- Place2 place2 = new Place2("baker");
-
- final Place defaultPlace = new Place() {
- };
-
- public void testEmptyToken() {
- historian.postToken("");
- assertEquals(defaultPlace, placeController.getWhere());
- }
-
- public void testGoToDefaultPlace() {
- placeController.goTo(defaultPlace);
- assertEquals("", historian.token);
- }
-
- public void testPlaceChange() {
- placeController.goTo(place1);
- assertEquals(subject.getPrefixAndToken(place1).toString(), historian.token);
- placeController.goTo(place2);
- assertEquals(subject.getPrefixAndToken(place2).toString(), historian.token);
- }
-
- public void testProperToken() {
- historian.postToken(subject.getPrefixAndToken(place1).toString());
- assertEquals(place1.content, ((Place1) placeController.getWhere()).content);
-
- historian.postToken(subject.getPrefixAndToken(place2).toString());
- assertEquals(place2.content, ((Place2) placeController.getWhere()).content);
- }
-
- public void testTheTestSubjectAndPrefixAndTokenToString() {
- String history1 = subject.getPrefixAndToken(place1).toString();
- assertEquals(PREFIX1 + ":" + place1.content, history1);
-
- String history2 = subject.getPrefixAndToken(place2).toString();
- assertEquals(PREFIX2 + ":" + place2.content, history2);
-
- assertEquals(subject.getFactory().tokenizer, subject.getTokenizer(PREFIX1));
- assertTrue(subject.getTokenizer(PREFIX2) instanceof Tokenizer2);
-
- Place place = new Place() {
- };
- assertNull(subject.getPrefixAndToken(place));
- assertNull(subject.getTokenizer("snot"));
- }
-
- public void testUnknownToken() {
- historian.postToken("abcdefghijklmnop");
- assertEquals(defaultPlace, placeController.getWhere());
- }
-
- @Override
- protected void setUp() {
- subject.setFactory(new TokenizerFactory());
- subject.register(placeController, eventBus, defaultPlace);
- };
-}
diff --git a/user/test/com/google/gwt/app/place/PlaceHistoryHandlerTest.java b/user/test/com/google/gwt/app/place/PlaceHistoryHandlerTest.java
new file mode 100644
index 0000000..5306086
--- /dev/null
+++ b/user/test/com/google/gwt/app/place/PlaceHistoryHandlerTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.gwt.app.place;
+
+import com.google.gwt.app.place.testplaces.Place1;
+import com.google.gwt.app.place.testplaces.Place2;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.event.shared.SimpleEventBus;
+
+import junit.framework.TestCase;
+
+import java.util.logging.Logger;
+
+/**
+ * Eponymous unit test.
+ */
+public class PlaceHistoryHandlerTest extends TestCase {
+ private static class MockHistorian implements
+ PlaceHistoryHandler.Historian {
+ final HandlerRegistration registration = new Registration();
+
+ ValueChangeHandler<String> handler;
+ String token = "";
+
+ public HandlerRegistration addValueChangeHandler(
+ ValueChangeHandler<String> valueChangeHandler) {
+ this.handler = valueChangeHandler;
+ return registration;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void newItem(String token, boolean issueEvent) {
+ assertFalse(issueEvent);
+ this.token = token;
+ }
+
+ public void postToken(String string) {
+ handler.onValueChange(new ValueChangeEvent<String>(string) {
+ });
+ }
+ }
+
+ private static class MockPlaceHistoryMapper implements PlaceHistoryMapper {
+
+ public Place getPlace(String token) {
+ if (TOKEN1.equals(token)) {
+ return PLACE1;
+ }
+ if (TOKEN2.equals(token)) {
+ return PLACE2;
+ }
+
+ return null;
+ }
+
+ public String getToken(Place place) {
+ if (place == PLACE1) {
+ return TOKEN1;
+ }
+ if (place == PLACE2) {
+ return TOKEN2;
+ }
+
+ return null;
+ }
+ }
+
+ private static class Registration implements HandlerRegistration {
+ public void removeHandler() {
+ throw new UnsupportedOperationException("Auto-generated method stub");
+ }
+ }
+
+ private class Subject extends PlaceHistoryHandler {
+
+ Subject(PlaceHistoryMapper mapper, Historian historian) {
+ super(mapper, historian);
+ }
+
+ @Override
+ Logger log() {
+ return deadLogger;
+ }
+ }
+
+ private static final String TOKEN1 = "t1";
+
+ private static final String TOKEN2 = "token2";
+
+ private static final Place1 PLACE1 = new Place1("able");
+
+ private static final Place2 PLACE2 = new Place2("baker");
+
+ Logger deadLogger = new Logger("shut up", null) {
+ };
+
+ PlaceController placeController;
+
+ MockHistorian historian;
+
+ Subject subject;
+
+ final Place defaultPlace = new Place() {
+ };
+
+ public void testEmptyToken() {
+ historian.postToken("");
+ assertEquals(defaultPlace, placeController.getWhere());
+ }
+
+ public void testGoToDefaultPlace() {
+ placeController.goTo(defaultPlace);
+ assertEquals("", historian.token);
+ }
+
+ public void testPlaceChange() {
+ placeController.goTo(PLACE1);
+ assertEquals(TOKEN1, historian.token);
+ placeController.goTo(PLACE2);
+ assertEquals(TOKEN2, historian.token);
+ }
+
+ public void testProperToken() {
+ historian.postToken(TOKEN1);
+ assertEquals(PLACE1, placeController.getWhere());
+
+ historian.postToken(TOKEN2);
+ assertEquals(PLACE2, placeController.getWhere());
+ }
+
+ public void testUnknownToken() {
+ historian.postToken("abcdefghijklmnop");
+ assertEquals(defaultPlace, placeController.getWhere());
+ }
+
+ @Override
+ protected void setUp() {
+ EventBus eventBus = new SimpleEventBus();
+ historian = new MockHistorian();
+ placeController = new PlaceController(eventBus,
+ new MockPlaceControllerDelegate()) {
+ @Override
+ Logger log() {
+ return deadLogger;
+ }
+ };
+ subject = new Subject(new MockPlaceHistoryMapper(), historian);
+ subject.register(placeController, eventBus, defaultPlace);
+ };
+}
diff --git a/user/test/com/google/gwt/app/place/PlaceHistoryHandlerGeneratorTest.java b/user/test/com/google/gwt/app/place/impl/PlaceHistoryMapperGeneratorTest.java
similarity index 72%
rename from user/test/com/google/gwt/app/place/PlaceHistoryHandlerGeneratorTest.java
rename to user/test/com/google/gwt/app/place/impl/PlaceHistoryMapperGeneratorTest.java
index 16bd4b9..51ba94e 100644
--- a/user/test/com/google/gwt/app/place/PlaceHistoryHandlerGeneratorTest.java
+++ b/user/test/com/google/gwt/app/place/impl/PlaceHistoryMapperGeneratorTest.java
@@ -13,14 +13,19 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.app.place.impl;
-import com.google.gwt.app.place.testplacehandler.NoFactory;
-import com.google.gwt.app.place.testplacehandler.WithFactory;
+import com.google.gwt.app.place.Place;
+import com.google.gwt.app.place.PlaceHistoryMapper;
+import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
+import com.google.gwt.app.place.WithTokenizers;
+import com.google.gwt.app.place.testplacemappers.NoFactory;
+import com.google.gwt.app.place.testplacemappers.WithFactory;
import com.google.gwt.app.place.testplaces.Place1;
import com.google.gwt.app.place.testplaces.Place2;
import com.google.gwt.app.place.testplaces.Place3;
import com.google.gwt.app.place.testplaces.Place4;
+import com.google.gwt.app.place.testplaces.Place5;
import com.google.gwt.app.place.testplaces.Tokenizer2;
import com.google.gwt.app.place.testplaces.Tokenizer3;
import com.google.gwt.app.place.testplaces.Tokenizer4;
@@ -29,38 +34,39 @@
import com.google.gwt.junit.client.GWTTestCase;
/**
- * Functional test of PlaceHistoryHandlerGenerator.
+ * Functional test of PlaceHistoryMapperGenerator.
*/
-public class PlaceHistoryHandlerGeneratorTest extends GWTTestCase {
+public class PlaceHistoryMapperGeneratorTest extends GWTTestCase {
@WithTokenizers( {
Place1.Tokenizer.class, Tokenizer2.class, Tokenizer3.class,
Tokenizer4.class})
- interface LocalNoFactory extends PlaceHistoryHandler {
+ interface LocalNoFactory extends PlaceHistoryMapper {
};
@WithTokenizers(Tokenizer4.class)
interface LocalWithFactory extends
- PlaceHistoryHandlerWithFactory<TokenizerFactory> {
+ PlaceHistoryMapperWithFactory<TokenizerFactory> {
};
@Override
public String getModuleName() {
- return "com.google.gwt.app.AppSuite";
+ return "com.google.gwt.app.App";
}
Place1 place1 = new Place1("able");
Place2 place2 = new Place2("baker");
Place3 place3 = new Place3("charlie");
Place4 place4 = new Place4("delta");
+ Place5 place5 = new Place5("echo");
public void testTopLevelWithoutFactory() {
- AbstractPlaceHistoryHandler<?> subject = GWT.create(NoFactory.class);
+ AbstractPlaceHistoryMapper<?> subject = GWT.create(NoFactory.class);
doTest(subject, null);
}
public void testTopLevelWithFactory() {
- AbstractPlaceHistoryHandler<TokenizerFactory> subject = GWT.create(WithFactory.class);
+ AbstractPlaceHistoryMapper<TokenizerFactory> subject = GWT.create(WithFactory.class);
TokenizerFactory factory = new TokenizerFactory();
subject.setFactory(factory);
@@ -68,21 +74,20 @@
}
public void testNestedWithoutFactory() {
- AbstractPlaceHistoryHandler<?> subject = GWT.create(LocalNoFactory.class);
+ AbstractPlaceHistoryMapper<?> subject = GWT.create(LocalNoFactory.class);
doTest(subject, null);
}
public void testNestedWithFactory() {
- AbstractPlaceHistoryHandler<TokenizerFactory> subject = GWT.create(LocalWithFactory.class);
+ AbstractPlaceHistoryMapper<TokenizerFactory> subject = GWT.create(LocalWithFactory.class);
TokenizerFactory factory = new TokenizerFactory();
subject.setFactory(factory);
doTest(subject, factory);
}
- // CHECKSTYLE_OFF
- private void doTest(AbstractPlaceHistoryHandler<?> subject,
+ private void doTest(AbstractPlaceHistoryMapper<?> subject,
TokenizerFactory factory) {
String history1 = subject.getPrefixAndToken(place1).toString();
assertEquals(Place1.Tokenizer.PREFIX + ":" + place1.content, history1);
@@ -92,20 +97,18 @@
assertEquals(TokenizerFactory.PLACE2_PREFIX + ":" + place2.content,
history2);
} else {
- // CHECKSTYLE_OFF
assertEquals("Place2:" + place2.content, history2);
- // CHECKSTYLE_ON
}
String history3 = subject.getPrefixAndToken(place3).toString();
- // CHECKSTYLE_OFF
assertEquals("Place3:" + place3.content, history3);
- // CHECKSTYLE_ON
String history4 = subject.getPrefixAndToken(place4).toString();
- // CHECKSTYLE_OFF
assertEquals("Place4:" + place4.content, history4);
- // CHECKSTYLE_ON
+
+ // Place 5 extends Place3 and does not have its own PlaceTokenizer
+ String history5 = subject.getPrefixAndToken(place5).toString();
+ assertEquals("Place3:" + place5.content, history5);
if (factory != null) {
assertEquals(factory.tokenizer,
diff --git a/user/test/com/google/gwt/app/place/testplacehandler/NoFactory.java b/user/test/com/google/gwt/app/place/testplacemappers/NoFactory.java
similarity index 84%
rename from user/test/com/google/gwt/app/place/testplacehandler/NoFactory.java
rename to user/test/com/google/gwt/app/place/testplacemappers/NoFactory.java
index a3bdac4..9a7f803 100644
--- a/user/test/com/google/gwt/app/place/testplacehandler/NoFactory.java
+++ b/user/test/com/google/gwt/app/place/testplacemappers/NoFactory.java
@@ -13,9 +13,9 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplacehandler;
+package com.google.gwt.app.place.testplacemappers;
-import com.google.gwt.app.place.PlaceHistoryHandler;
+import com.google.gwt.app.place.PlaceHistoryMapper;
import com.google.gwt.app.place.WithTokenizers;
import com.google.gwt.app.place.testplaces.Place1;
import com.google.gwt.app.place.testplaces.Tokenizer2;
@@ -23,10 +23,10 @@
import com.google.gwt.app.place.testplaces.Tokenizer4;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
@WithTokenizers( {
Place1.Tokenizer.class, Tokenizer2.class, Tokenizer3.class,
Tokenizer4.class})
-public interface NoFactory extends PlaceHistoryHandler {
+public interface NoFactory extends PlaceHistoryMapper {
}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/app/place/testplacehandler/WithFactory.java b/user/test/com/google/gwt/app/place/testplacemappers/WithFactory.java
similarity index 82%
rename from user/test/com/google/gwt/app/place/testplacehandler/WithFactory.java
rename to user/test/com/google/gwt/app/place/testplacemappers/WithFactory.java
index 644fe04..bdcb6f1 100644
--- a/user/test/com/google/gwt/app/place/testplacehandler/WithFactory.java
+++ b/user/test/com/google/gwt/app/place/testplacemappers/WithFactory.java
@@ -13,17 +13,17 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplacehandler;
+package com.google.gwt.app.place.testplacemappers;
-import com.google.gwt.app.place.PlaceHistoryHandlerWithFactory;
+import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
import com.google.gwt.app.place.WithTokenizers;
import com.google.gwt.app.place.testplaces.Tokenizer4;
import com.google.gwt.app.place.testplaces.TokenizerFactory;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
@WithTokenizers(Tokenizer4.class)
public interface WithFactory extends
- PlaceHistoryHandlerWithFactory<TokenizerFactory> {
+ PlaceHistoryMapperWithFactory<TokenizerFactory> {
}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place1.java b/user/test/com/google/gwt/app/place/testplaces/Place1.java
index 52ecc3b..0e4dd55 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place1.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Place1.java
@@ -20,7 +20,7 @@
import com.google.gwt.app.place.Prefix;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place1 extends Place {
public final String content;
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place2.java b/user/test/com/google/gwt/app/place/testplaces/Place2.java
index 04dac76..425a5bb 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place2.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Place2.java
@@ -18,7 +18,7 @@
import com.google.gwt.app.place.Place;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place2 extends Place {
public final String content;
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place3.java b/user/test/com/google/gwt/app/place/testplaces/Place3.java
index ebb6faa..2ec0c64 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place3.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Place3.java
@@ -15,15 +15,12 @@
*/
package com.google.gwt.app.place.testplaces;
-import com.google.gwt.app.place.Place;
-
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
-public class Place3 extends Place {
- public final String content;
+public class Place3 extends Place1 {
public Place3(String token) {
- this.content = token;
+ super(token);
}
}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place4.java b/user/test/com/google/gwt/app/place/testplaces/Place4.java
index 2aaa999..3c98fee 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place4.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Place4.java
@@ -15,15 +15,12 @@
*/
package com.google.gwt.app.place.testplaces;
-import com.google.gwt.app.place.Place;
-
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
-public class Place4 extends Place {
- public final String content;
+public class Place4 extends Place1 {
public Place4(String token) {
- this.content = token;
+ super(token);
}
}
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java b/user/test/com/google/gwt/app/place/testplaces/Place5.java
similarity index 68%
copy from user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java
copy to user/test/com/google/gwt/app/place/testplaces/Place5.java
index cdc38ab..47bfb1a 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryHandlerWithFactory.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Place5.java
@@ -13,15 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.app.place.testplaces;
/**
- * A PlaceHistoryHandler that can get its {@link PlaceTokenizer} instances from
- * a factory.
- *
- * @param <F> factory type
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
-public interface PlaceHistoryHandlerWithFactory<F> extends PlaceHistoryHandler {
+public class Place5 extends Place3 {
- void setFactory(F factory);
+ public Place5(String token) {
+ super(token);
+ }
}
diff --git a/user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java b/user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java
index 87c76f3..dc3d772 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java
@@ -18,7 +18,7 @@
import com.google.gwt.app.place.PlaceTokenizer;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
public class Tokenizer2 implements PlaceTokenizer<Place2> {
public Place2 getPlace(String token) {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java b/user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java
index 664f17e..f8a129a 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java
@@ -18,7 +18,7 @@
import com.google.gwt.app.place.PlaceTokenizer;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
public class Tokenizer3 implements PlaceTokenizer<Place3> {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java b/user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java
index 141b278..089ca8c 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java
+++ b/user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java
@@ -18,7 +18,7 @@
import com.google.gwt.app.place.PlaceTokenizer;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
public class Tokenizer4 implements PlaceTokenizer<Place4> {
public Place4 getPlace(String token) {
diff --git a/user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java b/user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java
index d6a291c..60046b4 100644
--- a/user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java
+++ b/user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java
@@ -19,7 +19,7 @@
import com.google.gwt.app.place.Prefix;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryHandlerGenerator}.
+ * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
*/
public class TokenizerFactory {
public static final String PLACE2_PREFIX = "p2";
diff --git a/user/test/com/google/gwt/app/rebind/EmptyMockJavaResource.java b/user/test/com/google/gwt/app/rebind/EmptyMockJavaResource.java
new file mode 100644
index 0000000..eb3c5d3
--- /dev/null
+++ b/user/test/com/google/gwt/app/rebind/EmptyMockJavaResource.java
@@ -0,0 +1,54 @@
+/*
+ * 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.gwt.app.rebind;
+
+import com.google.gwt.dev.javac.impl.MockJavaResource;
+
+/**
+ * Constructs an empty interface representation of a type.
+ * <p>
+ * Copied from {@link com.google.gwt.editor.rebind.model.EditorModelTest}
+ * pending a public API.
+ */
+class EmptyMockJavaResource extends MockJavaResource {
+ private final StringBuilder code = new StringBuilder();
+
+ public EmptyMockJavaResource(Class<?> clazz) {
+ super(clazz.getName());
+
+ code.append("package ").append(clazz.getPackage().getName()).append(";\n");
+ code.append("public interface ").append(clazz.getSimpleName());
+
+ int numParams = clazz.getTypeParameters().length;
+ if (numParams != 0) {
+ code.append("<");
+ for (int i = 0; i < numParams; i++) {
+ if (i != 0) {
+ code.append(",");
+ }
+ code.append("T").append(i);
+ }
+ code.append(">");
+ }
+
+ code.append("{}\n");
+ }
+
+ @Override
+ protected CharSequence getContent() {
+ return code;
+ }
+}
diff --git a/user/test/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java b/user/test/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
new file mode 100644
index 0000000..8f5dcbe
--- /dev/null
+++ b/user/test/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.gwt.app.rebind;
+
+import com.google.gwt.app.place.Place;
+import com.google.gwt.app.place.PlaceTokenizer;
+import com.google.gwt.app.place.Prefix;
+import com.google.gwt.app.place.testplaces.Place1;
+import com.google.gwt.app.place.testplaces.Place2;
+import com.google.gwt.app.place.testplaces.Place3;
+import com.google.gwt.app.place.testplaces.Place4;
+import com.google.gwt.app.place.testplaces.Place5;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.javac.CompilationState;
+import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dev.javac.impl.JavaResourceBase;
+import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Test case for {@link MostToLeastDerivedPlaceTypeComparator} that uses mock
+ * CompilationStates.
+ */
+public class MostToLeastDerivedPlaceTypeComparatorTest extends TestCase {
+
+ private static TreeLogger createCompileLogger() {
+ PrintWriterTreeLogger logger = new PrintWriterTreeLogger(new PrintWriter(
+ System.err, true));
+ logger.setMaxDetail(TreeLogger.ERROR);
+ return logger;
+ }
+
+ private TypeOracle typeOracle;
+
+ private Comparator<JClassType> comparator;
+
+ private JClassType place;
+ private JClassType place1;
+ private JClassType place2;
+ private JClassType place3;
+ private JClassType place4;
+ private JClassType place5;
+
+ @Override
+ protected void setUp() throws Exception {
+ comparator = new MostToLeastDerivedPlaceTypeComparator();
+
+ TreeLogger logger = createCompileLogger();
+ CompilationState state = CompilationStateBuilder.buildFrom(logger,
+ getJavaResources());
+ typeOracle = state.getTypeOracle();
+
+ place = typeOracle.getType("com.google.gwt.app.place.Place");
+ assertNotNull(place);
+ place1 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place1");
+ assertNotNull(place1);
+ place2 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place2");
+ assertNotNull(place2);
+ place3 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place3");
+ assertNotNull(place3);
+ place4 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place4");
+ assertNotNull(place4);
+ place5 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place5");
+ assertNotNull(place5);
+ }
+
+ private Set<Resource> getJavaResources() {
+ Set<Resource> rtn = new HashSet<Resource>(
+ Arrays.asList(JavaResourceBase.getStandardResources()));
+ rtn.add(new RealJavaResource(Place.class));
+ // referenced by Place1
+ rtn.add(new RealJavaResource(PlaceTokenizer.class));
+ // referenced by Place1.Tokenizer
+ rtn.add(new RealJavaResource(Prefix.class));
+ rtn.add(new RealJavaResource(Place1.class));
+ rtn.add(new RealJavaResource(Place2.class));
+ rtn.add(new RealJavaResource(Place3.class));
+ rtn.add(new RealJavaResource(Place4.class));
+ rtn.add(new RealJavaResource(Place5.class));
+ return rtn;
+ }
+
+ public void testEquality() {
+ for (JClassType p : new JClassType[] {
+ place, place1, place2, place3, place4, place5}) {
+ assertEquals(0, comparator.compare(p, p));
+ }
+ }
+
+ public void testPlaceComparesGreaterThanAnyDerivedClass() {
+ for (JClassType p : new JClassType[] {
+ place1, place2, place3, place4, place5}) {
+ assertEquals(1, (int) Math.signum(comparator.compare(place, p)));
+ assertEquals(-1, (int) Math.signum(comparator.compare(p, place)));
+ }
+ }
+
+ public void testPlaceInheritanceOrder() {
+ // Place3 extends Place1
+ assertEquals(1, (int) Math.signum(comparator.compare(place1, place3)));
+ assertEquals(-1, (int) Math.signum(comparator.compare(place3, place1)));
+
+ // Place5 extends Place3 extends Place1
+ assertEquals(1, (int) Math.signum(comparator.compare(place1, place5)));
+ assertEquals(-1, (int) Math.signum(comparator.compare(place5, place1)));
+
+ // Place4 extends Place1
+ assertEquals(1, (int) Math.signum(comparator.compare(place1, place4)));
+ assertEquals(-1, (int) Math.signum(comparator.compare(place4, place1)));
+
+ // Place5 extends Place3
+ assertEquals(1, (int) Math.signum(comparator.compare(place3, place5)));
+ assertEquals(-1, (int) Math.signum(comparator.compare(place5, place3)));
+ }
+
+ public void testFallbackToClassName() {
+ // Array sorted from least derived to most derived. In each pair of adjacent
+ // values, neither place extends the other.
+ JClassType[] places = {place1, place2, place3, place4, place5};
+ for (int i = 0; i < places.length - 1; i++) {
+ assertEquals(-1, (int) Math.signum(comparator.compare(places[i],
+ places[i + 1])));
+ assertEquals(1, (int) Math.signum(comparator.compare(places[i + 1],
+ places[i])));
+ }
+ }
+}
diff --git a/user/test/com/google/gwt/app/rebind/PlaceHistoryGeneratorContextTest.java b/user/test/com/google/gwt/app/rebind/PlaceHistoryGeneratorContextTest.java
new file mode 100644
index 0000000..c188e13
--- /dev/null
+++ b/user/test/com/google/gwt/app/rebind/PlaceHistoryGeneratorContextTest.java
@@ -0,0 +1,364 @@
+/*
+ * 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.gwt.app.rebind;
+
+import com.google.gwt.app.place.Place;
+import com.google.gwt.app.place.PlaceHistoryMapper;
+import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
+import com.google.gwt.app.place.PlaceTokenizer;
+import com.google.gwt.app.place.Prefix;
+import com.google.gwt.app.place.WithTokenizers;
+import com.google.gwt.app.place.testplacemappers.NoFactory;
+import com.google.gwt.app.place.testplacemappers.WithFactory;
+import com.google.gwt.app.place.testplaces.Place1;
+import com.google.gwt.app.place.testplaces.Place2;
+import com.google.gwt.app.place.testplaces.Place3;
+import com.google.gwt.app.place.testplaces.Place4;
+import com.google.gwt.app.place.testplaces.Tokenizer2;
+import com.google.gwt.app.place.testplaces.Tokenizer3;
+import com.google.gwt.app.place.testplaces.Tokenizer4;
+import com.google.gwt.app.place.testplaces.TokenizerFactory;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JType;
+import com.google.gwt.core.ext.typeinfo.NotFoundException;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dev.javac.impl.JavaResourceBase;
+import com.google.gwt.dev.javac.impl.MockJavaResource;
+import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.util.UnitTestTreeLogger;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Test case for {@link PlaceHistoryGeneratorContext} that uses mock
+ * CompilationStates.
+ */
+public class PlaceHistoryGeneratorContextTest extends TestCase {
+
+ private static final JType[] EMPTY_JTYPE_ARRAY = new JType[0];
+
+ private static TreeLogger createCompileLogger() {
+ PrintWriterTreeLogger logger = new PrintWriterTreeLogger(new PrintWriter(
+ System.err, true));
+ logger.setMaxDetail(TreeLogger.ERROR);
+ return logger;
+ }
+
+ private static TypeOracle createTypeOracle(Resource... resources) {
+ Set<Resource> rtn = new HashSet<Resource>(
+ Arrays.asList(JavaResourceBase.getStandardResources()));
+ rtn.add(new RealJavaResource(Place.class));
+ rtn.add(new RealJavaResource(PlaceTokenizer.class));
+ rtn.add(new RealJavaResource(PlaceHistoryMapper.class));
+ rtn.add(new RealJavaResource(PlaceHistoryMapperWithFactory.class));
+ rtn.add(new RealJavaResource(WithTokenizers.class));
+ rtn.add(new RealJavaResource(Prefix.class));
+ rtn.add(new RealJavaResource(NoFactory.class));
+ rtn.add(new RealJavaResource(WithFactory.class));
+ rtn.add(new RealJavaResource(TokenizerFactory.class));
+ rtn.add(new RealJavaResource(Place1.class));
+ rtn.add(new RealJavaResource(Place2.class));
+ rtn.add(new RealJavaResource(Place3.class));
+ rtn.add(new RealJavaResource(Place4.class));
+ rtn.add(new RealJavaResource(Tokenizer2.class));
+ rtn.add(new RealJavaResource(Tokenizer3.class));
+ rtn.add(new RealJavaResource(Tokenizer4.class));
+ rtn.addAll(Arrays.asList(resources));
+ return CompilationStateBuilder.buildFrom(createCompileLogger(), rtn).getTypeOracle();
+ }
+
+ public void testCreateNoFactory() throws UnableToCompleteException,
+ NotFoundException {
+ doTestCreate(NoFactory.class, null);
+ }
+
+ public void testCreateWithFactory() throws UnableToCompleteException,
+ NotFoundException {
+ doTestCreate(WithFactory.class, TokenizerFactory.class);
+ }
+
+ public void testNoFactory() throws UnableToCompleteException,
+ NotFoundException {
+
+ TypeOracle typeOracle = createTypeOracle();
+ JClassType place1 = typeOracle.getType(Place1.class.getName());
+ JClassType place2 = typeOracle.getType(Place2.class.getName());
+ JClassType place3 = typeOracle.getType(Place3.class.getName());
+ JClassType place4 = typeOracle.getType(Place4.class.getName());
+
+ PlaceHistoryGeneratorContext context = createContext(TreeLogger.NULL,
+ typeOracle, NoFactory.class.getName(), null);
+
+ // Found all place prefixes?
+ assertEquals(new HashSet<String>(Arrays.asList(Place1.Tokenizer.PREFIX,
+ "Place2", "Place3", "Place4")), context.getPrefixes());
+
+ // Found all place types and correctly sorted them?
+ assertEquals(Arrays.asList(place3, place4, place1, place2),
+ new ArrayList<JClassType>(context.getPlaceTypes()));
+
+ // correctly maps place types to their prefixes?
+ assertEquals(Place1.Tokenizer.PREFIX, context.getPrefix(place1));
+ assertEquals("Place2", context.getPrefix(place2));
+ assertEquals("Place3", context.getPrefix(place3));
+ assertEquals("Place4", context.getPrefix(place4));
+
+ // there obviously shouldn't be factory methods
+ assertNull(context.getTokenizerGetter(Place1.Tokenizer.PREFIX));
+ assertNull(context.getTokenizerGetter("Place2"));
+ assertNull(context.getTokenizerGetter("Place3"));
+ assertNull(context.getTokenizerGetter("Place4"));
+
+ // correctly maps prefixes to their tokenizer type?
+ assertEquals(typeOracle.getType(Place1.Tokenizer.class.getCanonicalName()),
+ context.getTokenizerType(Place1.Tokenizer.PREFIX));
+ assertEquals(typeOracle.getType(Tokenizer2.class.getName()),
+ context.getTokenizerType("Place2"));
+ assertEquals(typeOracle.getType(Tokenizer3.class.getName()),
+ context.getTokenizerType("Place3"));
+ assertEquals(typeOracle.getType(Tokenizer4.class.getName()),
+ context.getTokenizerType("Place4"));
+ }
+
+ public void testWithFactory() throws UnableToCompleteException,
+ NotFoundException {
+
+ TypeOracle typeOracle = createTypeOracle();
+
+ JClassType place1 = typeOracle.getType(Place1.class.getName());
+ JClassType place2 = typeOracle.getType(Place2.class.getName());
+ JClassType place3 = typeOracle.getType(Place3.class.getName());
+ JClassType place4 = typeOracle.getType(Place4.class.getName());
+ JClassType factory = typeOracle.getType(TokenizerFactory.class.getName());
+
+ PlaceHistoryGeneratorContext context = createContext(TreeLogger.NULL,
+ typeOracle, WithFactory.class.getName(),
+ TokenizerFactory.class.getName());
+
+ // Found all place prefixes?
+ assertEquals(new HashSet<String>(Arrays.asList(Place1.Tokenizer.PREFIX,
+ TokenizerFactory.PLACE2_PREFIX, "Place3", "Place4")),
+ context.getPrefixes());
+
+ // Found all place types and correctly sorted them?
+ assertEquals(Arrays.asList(place3, place4, place1, place2),
+ new ArrayList<JClassType>(context.getPlaceTypes()));
+
+ // correctly maps place types to their prefixes?
+ assertEquals(Place1.Tokenizer.PREFIX, context.getPrefix(place1));
+ assertEquals(TokenizerFactory.PLACE2_PREFIX, context.getPrefix(place2));
+ assertEquals("Place3", context.getPrefix(place3));
+ assertEquals("Place4", context.getPrefix(place4));
+
+ // correctly map prefixes to their factory method (or null)?
+ assertEquals(factory.getMethod("getTokenizer1", EMPTY_JTYPE_ARRAY),
+ context.getTokenizerGetter(Place1.Tokenizer.PREFIX));
+ assertEquals(factory.getMethod("getTokenizer2", EMPTY_JTYPE_ARRAY),
+ context.getTokenizerGetter(TokenizerFactory.PLACE2_PREFIX));
+ assertEquals(factory.getMethod("getTokenizer3", EMPTY_JTYPE_ARRAY),
+ context.getTokenizerGetter("Place3"));
+ assertNull(context.getTokenizerGetter("Place4"));
+
+ // correctly maps prefixes to their tokenizer type (or null)?
+ assertNull(context.getTokenizerType(Place1.Tokenizer.PREFIX));
+ assertNull(context.getTokenizerType(TokenizerFactory.PLACE2_PREFIX));
+ assertNull(context.getTokenizerType("Place3"));
+ assertEquals(typeOracle.getType(Tokenizer4.class.getName()),
+ context.getTokenizerType("Place4"));
+ }
+
+ public void testDuplicatePrefix() {
+ MockJavaResource intf = new MockJavaResource("my.MyPlaceHistoryMapper") {
+
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package my;\n");
+ code.append("import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;\n");
+ code.append("import com.google.gwt.app.place.WithTokenizers;\n");
+ code.append("import com.google.gwt.app.place.Prefix;\n");
+ code.append("import com.google.gwt.app.place.testplaces.Place1;\n");
+ code.append("import com.google.gwt.app.place.testplaces.Tokenizer2;\n");
+
+ code.append("@WithTokenizers(Place1.Tokenizer.class)\n");
+ code.append("public interface MyPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyPlaceHistoryMapper.Factory> {\n");
+ code.append(" interface Factory {\n");
+ code.append(" @Prefix(Place1.Tokenizer.PREFIX) Tokenizer2 tokenizer2();\n");
+ code.append(" }\n");
+ code.append("}\n");
+ return code;
+ }
+ };
+
+ TypeOracle typeOracle = createTypeOracle(intf);
+
+ UnitTestTreeLogger.Builder loggerBuilder = new UnitTestTreeLogger.Builder();
+ loggerBuilder.expectError(String.format(
+ "Found duplicate place prefix \"%s\" on %s, already seen on %s",
+ Place1.Tokenizer.PREFIX, Place1.Tokenizer.class.getCanonicalName(),
+ intf.getTypeName() + ".Factory#tokenizer2()"), null);
+ UnitTestTreeLogger logger = loggerBuilder.createLogger();
+
+ PlaceHistoryGeneratorContext context = createContext(logger, typeOracle,
+ intf.getTypeName(), intf.getTypeName() + ".Factory");
+
+ try {
+ context.ensureInitialized();
+ fail();
+ } catch (UnableToCompleteException e) {
+ // expected exception
+ }
+
+ logger.assertCorrectLogEntries();
+ }
+
+ public void testDuplicatePlaceType() {
+ MockJavaResource intf = new MockJavaResource("my.MyPlaceHistoryMapper") {
+
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package my;\n");
+ code.append("import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;\n");
+ code.append("import com.google.gwt.app.place.PlaceTokenizer;\n");
+ code.append("import com.google.gwt.app.place.WithTokenizers;\n");
+ code.append("import com.google.gwt.app.place.Prefix;\n");
+ code.append("import com.google.gwt.app.place.testplaces.Place1;\n");
+
+ code.append("@WithTokenizers(Place1.Tokenizer.class)\n");
+ code.append("public interface MyPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyPlaceHistoryMapper.Factory> {\n");
+ code.append(" interface Factory {\n");
+ code.append(" @Prefix(\"anotherPrefix\") PlaceTokenizer<Place1> bar();\n");
+ code.append(" }\n");
+ code.append("}\n");
+ return code;
+ }
+ };
+
+ TypeOracle typeOracle = createTypeOracle(intf);
+
+ UnitTestTreeLogger.Builder loggerBuilder = new UnitTestTreeLogger.Builder();
+ loggerBuilder.expectError(
+ String.format(
+ "Found duplicate tokenizer's place type \"%s\" on %s, already seen on %s",
+ Place1.class.getName(), Place1.Tokenizer.class.getCanonicalName(),
+ intf.getTypeName() + ".Factory#bar()"), null);
+ UnitTestTreeLogger logger = loggerBuilder.createLogger();
+
+ PlaceHistoryGeneratorContext context = createContext(logger, typeOracle,
+ intf.getTypeName(), intf.getTypeName() + ".Factory");
+
+ try {
+ context.ensureInitialized();
+ fail();
+ } catch (UnableToCompleteException e) {
+ // expected exception
+ }
+
+ logger.assertCorrectLogEntries();
+ }
+
+ public void testPrefixContainingColon() {
+ MockJavaResource intf = new MockJavaResource("my.MyPlaceHistoryMapper") {
+
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package my;\n");
+ code.append("import com.google.gwt.app.place.Place;\n");
+ code.append("import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;\n");
+ code.append("import com.google.gwt.app.place.PlaceTokenizer;\n");
+ code.append("import com.google.gwt.app.place.Prefix;\n");
+
+ code.append("public interface MyPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyPlaceHistoryMapper.Factory> {\n");
+ code.append(" interface Factory {\n");
+ code.append(" @Prefix(\"foo:bar\") PlaceTokenizer<Place> foo_bar();\n");
+ code.append(" }\n");
+ code.append("}\n");
+ return code;
+ }
+ };
+
+ TypeOracle typeOracle = createTypeOracle(intf);
+
+ UnitTestTreeLogger.Builder loggerBuilder = new UnitTestTreeLogger.Builder();
+ loggerBuilder.expectError(
+ "Found place prefix \"foo:bar\" containing separator char \":\", on "
+ + intf.getTypeName() + ".Factory#foo_bar()", null);
+ UnitTestTreeLogger logger = loggerBuilder.createLogger();
+
+ PlaceHistoryGeneratorContext context = createContext(logger, typeOracle,
+ intf.getTypeName(), intf.getTypeName() + ".Factory");
+
+ try {
+ context.ensureInitialized();
+ fail();
+ } catch (UnableToCompleteException e) {
+ // expected exception
+ }
+
+ logger.assertCorrectLogEntries();
+ }
+
+ private void doTestCreate(Class<? extends PlaceHistoryMapper> intf,
+ Class<?> factory) throws UnableToCompleteException, NotFoundException {
+ UnitTestTreeLogger logger = new UnitTestTreeLogger.Builder().createLogger();
+
+ TypeOracle typeOracle = createTypeOracle();
+
+ PlaceHistoryGeneratorContext context = PlaceHistoryGeneratorContext.create(
+ logger, typeOracle, intf.getName());
+
+ assertEquals(typeOracle.getType(String.class.getName()), context.stringType);
+ assertEquals(typeOracle.getType(PlaceTokenizer.class.getName()),
+ context.placeTokenizerType);
+ assertSame(logger, context.logger);
+ assertSame(typeOracle, context.typeOracle);
+
+ assertEquals(typeOracle.getType(intf.getName()), context.interfaceType);
+
+ if (factory == null) {
+ assertNull(context.factoryType);
+ } else {
+ assertEquals(typeOracle.getType(factory.getName()), context.factoryType);
+ }
+
+ assertEquals(intf.getSimpleName() + "Impl", context.implName);
+ assertEquals(intf.getPackage().getName(), context.packageName);
+
+ logger.assertCorrectLogEntries();
+ }
+
+ private PlaceHistoryGeneratorContext createContext(TreeLogger logger,
+ TypeOracle typeOracle, String interfaceName, String factoryName) {
+ return new PlaceHistoryGeneratorContext(logger, typeOracle,
+ typeOracle.findType(interfaceName), //
+ typeOracle.findType(factoryName), //
+ typeOracle.findType(String.class.getName()), //
+ typeOracle.findType(PlaceTokenizer.class.getName()), //
+ null, null);
+ }
+}
diff --git a/user/test/com/google/gwt/app/rebind/RealJavaResource.java b/user/test/com/google/gwt/app/rebind/RealJavaResource.java
new file mode 100644
index 0000000..a18e161
--- /dev/null
+++ b/user/test/com/google/gwt/app/rebind/RealJavaResource.java
@@ -0,0 +1,43 @@
+/*
+ * 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.gwt.app.rebind;
+
+import com.google.gwt.dev.javac.impl.MockJavaResource;
+import com.google.gwt.dev.util.Util;
+
+import java.io.InputStream;
+
+/**
+ * Loads the actual source of a type. This should be used only for types
+ * directly tested by this package's tests. Note that use of this class
+ * requires your source files to be on your classpath.
+ * <p>
+ * Copied from {@link com.google.gwt.editor.rebind.model.EditorModelTest}
+ * pending a public API.
+ */
+class RealJavaResource extends MockJavaResource {
+ public RealJavaResource(Class<?> clazz) {
+ super(clazz.getName());
+ }
+
+ @Override
+ protected CharSequence getContent() {
+ String resourceName = getTypeName().replace('.', '/') + ".java";
+ InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(
+ resourceName);
+ return Util.readStreamAsString(stream);
+ }
+}
diff --git a/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java b/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
index 1fc7f51..bdb1139 100644
--- a/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
+++ b/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
@@ -94,7 +94,8 @@
/**
* Loads the actual source of a type. This should be used only for types
- * directly tested by this test.
+ * directly tested by this test. Note that use of this class requires your
+ * source files to be on your classpath.
*/
private static class RealJavaResource extends MockJavaResource {
public RealJavaResource(Class<?> clazz) {