Allow primary keys to be any type, and test it.
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / client / place / DetailsPlace.java
1 /*
2  * Copyright (C) 2011 Openismus GmbH
3  *
4  * This file is part of GWT-Glom.
5  *
6  * GWT-Glom is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * GWT-Glom is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with GWT-Glom.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package org.glom.web.client.place;
21
22 import java.util.HashMap;
23
24 import org.glom.web.client.StringUtils;
25 import org.glom.web.shared.TypedDataItem;
26 import org.glom.web.shared.libglom.Field.GlomFieldType;
27
28 import com.google.gwt.place.shared.PlaceTokenizer;
29 import com.google.gwt.place.shared.Prefix;
30
31 public class DetailsPlace extends HasTablePlace {
32         private final TypedDataItem primaryKeyValue;
33
34         public DetailsPlace(final String documentID, final String tableName, final TypedDataItem primarykeyValue) {
35                 super(documentID, tableName);
36                 this.primaryKeyValue = primarykeyValue;
37         }
38
39         public TypedDataItem getPrimaryKeyValue() {
40                 return primaryKeyValue;
41         }
42
43         @Prefix("details")
44         public static class Tokenizer extends HasTablePlace.Tokenizer implements PlaceTokenizer<DetailsPlace> {
45
46                 private final String primaryKeyValueKey = "value";
47
48                 /**
49                  * Creates the URL string that is shown in the browser. This is the bookmarked URL.
50                  * 
51                  * @see com.google.gwt.place.shared.PlaceTokenizer#getToken(com.google.gwt.place.shared.Place)
52                  * @see org.glom.web.server.Utils.getGlomTypeGdaValueForTypedDataItem(String, String, glom_field_type,
53                  *      TypedDataItem)
54                  */
55                 @Override
56                 public String getToken(final DetailsPlace place) {
57                         final TypedDataItem primaryKeyValue = place.getPrimaryKeyValue();
58                         final GlomFieldType glomFieldType = primaryKeyValue.getType();
59
60                         // create the URL string based on the
61                         String primaryKeyValueString = "";
62                         switch (glomFieldType) {
63                         case TYPE_NUMERIC:
64                                 // non-locale specific number-to-string conversion:
65                                 // http://docs.oracle.com/javase/6/docs/api/java/lang/Double.html#toString%28double%29
66                                 primaryKeyValueString = Double.toString(primaryKeyValue.getNumber()); //TODO: Handle other types.
67                                 // Remove the trailing point and zero on integers. This just makes URL string look nicer.
68                                 if (primaryKeyValueString.endsWith(".0")) {
69                                         primaryKeyValueString = primaryKeyValueString.substring(0, primaryKeyValueString.length() - 2);
70                                 }
71                                 break;
72
73                         case TYPE_TEXT:
74                                 primaryKeyValueString = primaryKeyValue.getText();
75                                 break;
76
77                         case TYPE_INVALID:
78                                 final String urlText = primaryKeyValue.getUnknown();
79                                 if (!primaryKeyValue.isEmpty() && urlText != null) {
80                                         // An invalid type that's not empty indicates that primary key value has been created from a URL
81                                         // string. Use the same string to represent the primary key value on the URL.
82                                         primaryKeyValueString = urlText;
83                                         // TODO: Update the primary key value string with the actual Gda Value that was created. The primary
84                                         // key value could be different if the string-to-number conversion doesn't work.
85                                 }
86                                 break;
87
88                         default:
89                                 // Unknown types are represented in the URL by an empty string. When loading a page with an unknown from
90                                 // a URL (bookmark or link), the details view will run the query with an empty Value item based on the
91                                 // type from the Glom document. The first result from this query will be shown. This means that the
92                                 // specific record for unknown types are not bookmarkmarkable.
93
94                                 // Support for bookmarking a new type can be added by adding a case statement for the new type here
95                                 // and in this method:
96                                 // org.glom.web.server.Utils.getGlomTypeGdaValueForTypedDataItem()
97
98                                 // primaryKeyValueString remains empty
99                                 break;
100                         }
101
102                         final HashMap<String, String> params = new HashMap<String, String>();
103                         params.put(documentKey, place.getDocumentID());
104                         params.put(tableKey, place.getTableName());
105                         params.put(primaryKeyValueKey, primaryKeyValueString);
106                         return buildParamsToken(params);
107                 }
108
109                 /**
110                  * Create a DetailPlace that should be loaded from a URL string. This is called when users load the details view
111                  * directly with the URL string (a bookmark or link).
112                  * 
113                  * @see com.google.gwt.place.shared.PlaceTokenizer#getPlace(java.lang.String)
114                  * @see org.glom.web.server.Utils.getGlomTypeGdaValueForTypedDataItem(String, String, glom_field_type,
115                  *      TypedDataItem)
116                  */
117                 @Override
118                 public DetailsPlace getPlace(final String token) {
119                         // default empty values
120                         String documentID = "";
121                         String tableName = ""; // an empty value represents the default table
122
123                         final TypedDataItem primaryKeyValue = new TypedDataItem();
124
125                         final HashMap<String, String> params = getTokenParams(token);
126
127                         if (params == null) {
128                                 return new DetailsPlace("", "", primaryKeyValue);
129                         }
130
131                         if (params.get(documentKey) != null) {
132                                 documentID = params.get(documentKey);
133                         }
134
135                         if (params.get(tableKey) != null) {
136                                 tableName = params.get(tableKey);
137                         }
138
139                         if (params.get(primaryKeyValueKey) != null) {
140                                 final String primaryKeyValueString = params.get(primaryKeyValueKey);
141                                 // Set as unknown because the type of the primary key is not known at this point. A proper primary key
142                                 // value will be created using the type from the Glom document in the servlet.
143                                 primaryKeyValue.setUnknown(primaryKeyValueString);
144                         }
145
146                         if (StringUtils.isEmpty(documentID)) {
147                                 // The documentID was not retrieved from the URL. Use empty values for the details place.
148                                 return new DetailsPlace("", "", primaryKeyValue);
149                         }
150
151                         return new DetailsPlace(documentID, tableName, primaryKeyValue);
152                 }
153         }
154
155 }