Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Just for future reference for people like me landed here and still have no answer. I´ve ended up with the following solution using GIN and Generators for a PlaceFactory.</p> <p>This is what my tokens look like now. eg: <strong>#EditUser/id:15/type:Agent</strong></p> <p>I have a AbstractPlace that every Place should extend from.</p> <pre><code>public abstract class AbstractPlace extends Place { public abstract Activity getActivity(); } </code></pre> <p>An example Place:</p> <pre><code>public class EditUserPlace extends AbstractPlace { private Long id; private User.Type type; //getters and setters @Override public Activity getActivity() { return App.getClientFactory().getEditUserPresenter().withPlace(this); } } </code></pre> <p>PlaceFactory interface for Defered binding:</p> <pre><code>public interface PlaceFactory { Place fromToken(String token); String toToken(Place place); } </code></pre> <p>and a annotation for registering place classes</p> <pre><code>public @interface WithPlaces { Class&lt;? extends Place&gt;[] value() default {}; } </code></pre> <p>and the PlaceFactoryGenerator</p> <p>Setup the generator in you GWT Module</p> <pre><code>&lt;generate-with class="app.rebind.place.PlaceFactoryGenerator"&gt; &lt;when-type-assignable class="app.client.common.AppPlaceFactory"/&gt; &lt;/generate-with&gt; public class PlaceFactoryGenerator extends Generator { private TreeLogger logger; private TypeOracle typeOracle; private JClassType interfaceType; private String packageName; private String implName; private Class&lt;? extends Place&gt;[] placeTypes; @Override public String generate(TreeLogger logger, GeneratorContext generatorContext, String interfaceName) throws UnableToCompleteException { this.logger = logger; this.typeOracle = generatorContext.getTypeOracle(); this.interfaceType = typeOracle.findType(interfaceName); this.packageName = interfaceType.getPackage().getName(); this.implName = interfaceType.getName().replace(".", "_") + "Impl"; // TODO Trocar annotation por scan WithPlaces places = interfaceType.getAnnotation(WithPlaces.class); assert (places != null); Class&lt;? extends Place&gt;[] placeTypes = places.value(); this.placeTypes = placeTypes; PrintWriter out = generatorContext.tryCreate(logger, packageName, implName); if (out != null) { generateOnce(generatorContext, out); } return packageName + "." + implName; } private void generateOnce(GeneratorContext generatorContext, PrintWriter out) { TreeLogger logger = this.logger.branch( TreeLogger.DEBUG, String.format("Generating implementation of %s", interfaceType)); ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory( packageName, implName); factory.addImport(interfaceType.getQualifiedSourceName()); factory.addImplementedInterface(interfaceType.getSimpleSourceName()); factory.addImport(StringBuilder.class.getCanonicalName()); factory.addImport(Map.class.getCanonicalName()); factory.addImport(HashMap.class.getCanonicalName()); factory.addImport(Place.class.getCanonicalName()); for (Class&lt;? extends Place&gt; place : placeTypes) factory.addImport(place.getCanonicalName()); SourceWriter sw = factory.createSourceWriter(generatorContext, out); sw.println("public Place fromToken(String token) {"); sw.indent(); sw.println("int barAt = token.indexOf('/');"); sw.println("String placeName = token;"); sw.println("Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();"); sw.println("if (barAt &gt; 0) {"); sw.indent(); sw.println("placeName = token.substring(0, barAt);"); sw.println("String[] keyValues = token.substring(barAt + 1).split(\"/\");"); sw.println("for (String item : keyValues) {"); sw.indent(); sw.println("int colonAt = item.indexOf(':');"); sw.println("if (colonAt &gt; 0) {"); sw.indent(); sw.println("String key = item.substring(0, colonAt);"); sw.println("String value = item.substring(colonAt + 1);"); sw.println("params.put(key, value);"); sw.outdent(); sw.println("}"); sw.outdent(); sw.println("}"); sw.outdent(); sw.println("}\n"); for (Class&lt;? extends Place&gt; placeType : placeTypes) { String placeTypeName = placeType.getSimpleName(); int replaceStrPos = placeTypeName.lastIndexOf("Place"); String placeName = placeTypeName.substring(0, replaceStrPos); sw.println("if (placeName.equals(\"%s\")) {", placeName); sw.indent(); sw.println("%s place = new %s();", placeTypeName, placeTypeName); generateSetExpressions(sw, placeType); sw.println("return place;"); sw.outdent(); sw.println("}\n"); } sw.println("return null;"); sw.outdent(); sw.println("}\n"); sw.println("public String toToken(Place place) {"); sw.indent(); sw.println("StringBuilder token = new StringBuilder();\n"); for (Class&lt;? extends Place&gt; placeType : placeTypes) { String placeTypeName = placeType.getSimpleName(); int replaceStrPos = placeTypeName.lastIndexOf("Place"); String placeName = placeTypeName.substring(0, replaceStrPos); sw.println("if (place instanceof %s) {", placeTypeName); sw.indent(); sw.println("%s newPlace = (%s)place;", placeTypeName, placeTypeName); sw.println("token.append(\"%s\");", placeName); generateTokenExpressions(sw, placeType); sw.println("return token.toString();"); sw.outdent(); sw.println("}\n"); } sw.println("return token.toString();"); sw.outdent(); sw.println("}\n"); sw.outdent(); sw.println("}"); generatorContext.commit(logger, out); } private void generateTokenExpressions(SourceWriter sw, Class&lt;? extends Place&gt; placeType) { for (Field field : placeType.getDeclaredFields()) { char[] fieldName = field.getName().toCharArray(); fieldName[0] = Character.toUpperCase(fieldName[0]); String getterName = "get" + new String(fieldName); sw.println("token.append(\"/%s:\");", field.getName()); sw.println("token.append(newPlace.%s().toString());", getterName); } } private void generateSetExpressions(SourceWriter sw, Class&lt;? extends Place&gt; placeType) { for (Field field : placeType.getDeclaredFields()) { char[] fieldName = field.getName().toCharArray(); fieldName[0] = Character.toUpperCase(fieldName[0]); String setterName = "set" + new String(fieldName); List&lt;Method&gt; methods = findMethods(placeType, setterName); for (Method method : methods) { Class&lt;?&gt;[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 0 || parameterTypes.length &gt; 1) continue; Class&lt;?&gt; parameterType = parameterTypes[0]; String exp = "%s"; if (parameterType == Character.class) { exp = "%s.charAt(0)"; } else if (parameterType == Boolean.class) { exp = "Boolean.parseBoolean(%s)"; } else if (parameterType == Byte.class) { exp = "Byte.parseInt(%s)"; } else if (parameterType == Short.class) { exp = "Short.parseShort(%s)"; } else if (parameterType == Integer.class) { exp = "Integer.parseInt(%s)"; } else if (parameterType == Long.class) { exp = "Long.parseLong(%s)"; } else if (parameterType == Float.class) { exp = "Float.parseFloat(%s)"; } else if (parameterType == Double.class) { exp = "Double.parseDouble(%s)"; } else if (parameterType.getSuperclass().isAssignableFrom(Enum.class)) { exp = parameterType.getCanonicalName() + ".valueOf(%s)"; } else if (parameterType != String.class){ continue; } String innerExp = String.format("params.get(\"%s\")", field.getName()); String wrapperExp = String.format(exp, innerExp); sw.println("place.%s(%s);", setterName, wrapperExp); } } } private List&lt;Method&gt; findMethods(Class&lt;? extends Place&gt; placeType, String name) { Method[] methods = placeType.getMethods(); List&lt;Method&gt; found = new ArrayList&lt;Method&gt;(); for (Method method : methods) { if (method.getName().equals(name)) { found.add(method); } } return found; } } </code></pre> <p>Whats my ActivityMapper look like?</p> <pre><code>public class AppActivityMapper implements ActivityMapper { public Activity getActivity(Place place) { AbstractPlace abstractPlace = (AbstractPlace)place; return abstractPlace.getActivity(); } } </code></pre> <p>We need a custom PlaceHistoryMapper </p> <pre><code>public class AppPlaceHistoryMapper implements PlaceHistoryMapper { private AppPlaceFactory placeFactory = GWT.create(AppPlaceFactory.class); public Place getPlace(String token) { return placeFactory.fromToken(token); } public String getToken(Place place) { return placeFactory.toToken(place); } } </code></pre> <p>And at last the PlaceFactory, this will be generated for just put your place classes in the annotation and be happy!</p> <pre><code>@WithPlaces(value = { HomePlace.class, EditUserPlace.class }) public interface AppPlaceFactory extends PlaceFactory { } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload