Replace deprecated DOM.setElementAttribute().
[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.Date;
23 import java.util.HashMap;
24
25 import org.glom.web.client.StringUtils;
26 import org.glom.web.shared.TypedDataItem;
27 import org.glom.web.shared.libglom.Field.GlomFieldType;
28
29 import com.google.gwt.i18n.shared.DateTimeFormat;
30 import com.google.gwt.place.shared.PlaceTokenizer;
31 import com.google.gwt.place.shared.Prefix;
32
33 public class DetailsPlace extends HasTablePlace {
34         private final TypedDataItem primaryKeyValue;
35
36         public DetailsPlace(final String documentID, final String tableName, final TypedDataItem primarykeyValue) {
37                 super(documentID, tableName);
38                 this.primaryKeyValue = primarykeyValue;
39         }
40
41         public TypedDataItem getPrimaryKeyValue() {
42                 return primaryKeyValue;
43         }
44
45         @Prefix("details")
46         public static class Tokenizer extends HasTablePlace.Tokenizer implements PlaceTokenizer<DetailsPlace> {
47
48                 private final String primaryKeyValueKey = "value";
49
50                 /**
51                  * Creates the URL string that is shown in the browser. This is the bookmarked URL.
52                  * 
53                  * @see com.google.gwt.place.shared.PlaceTokenizer#getToken(com.google.gwt.place.shared.Place)
54                  * @see org.glom.web.server.Utils.getGlomTypeGdaValueForTypedDataItem(String, String, glom_field_type,
55                  *      TypedDataItem)
56                  */
57                 @Override
58                 public String getToken(final DetailsPlace place) {
59                         // create the URL string:
60                         final String primaryKeyValueString = getStringForData(place.getPrimaryKeyValue());
61
62                         final HashMap<String, String> params = new HashMap<String, String>();
63                         params.put(documentKey, place.getDocumentID());
64                         params.put(tableKey, place.getTableName());
65                         params.put(primaryKeyValueKey, primaryKeyValueString);
66                         return buildParamsToken(params);
67                 }
68
69                 /**
70                  * Create a string representation of a database value, for use in a URL.
71                  * This return string should be parseable by Utils.transformUnknownToActualType()
72                  * on the server.
73                  * 
74                  * @param value
75                  * @param glomFieldType
76                  * @return
77                  */
78                 private String getStringForData(final TypedDataItem value) {
79                         final GlomFieldType glomFieldType = value.getType();
80
81                         String primaryKeyValueString = "";
82                         switch (glomFieldType) {
83                         case TYPE_NUMERIC:
84                                 // non-locale specific number-to-string conversion:
85                                 // http://docs.oracle.com/javase/6/docs/api/java/lang/Double.html#toString%28double%29
86                                 primaryKeyValueString = Double.toString(value.getNumber());
87                                 // Remove the trailing point and zero on integers. This just makes URL string look nicer.
88                                 if (primaryKeyValueString.endsWith(".0")) {
89                                         primaryKeyValueString = primaryKeyValueString.substring(0, primaryKeyValueString.length() - 2);
90                                 }
91                                 break;
92
93                         case TYPE_TEXT:
94                                 primaryKeyValueString = value.getText();
95                                 break;
96                                 
97                         case TYPE_BOOLEAN:
98                                 primaryKeyValueString = (value.getBoolean() ? "true" : "false");
99                                 break;
100
101                         case TYPE_DATE:
102                                 final Date date = value.getDate();
103                                 if(date == null) {
104                                         primaryKeyValueString = "";
105                                 } else {
106                                         //Note that almost any use of GWT's DateTimeFormat on the server causes an exception
107                                         //because it is not implemented.
108                                         //See http://code.google.com/p/google-web-toolkit/issues/detail?id=7671
109                                         
110                                         final DateTimeFormat dateTimeFomat = DateTimeFormat.getFormat("yyyy-MM-dd");
111                                         primaryKeyValueString = dateTimeFomat.format(date);
112                                         
113                                         //We could this manually, but date.getYear(), etc, are not available in client-side GWT code.
114                                         //
115                                         //primaryKeyValueString = String.format("%04d-%02d-%02d",
116                                         //              date.getYear() + 1900, date.getMonth() + 1, date.getDate());
117                                 }
118                         
119                                 break;
120
121                         case TYPE_INVALID:
122                                 final String urlText = value.getUnknown();
123                                 if (!value.isEmpty() && urlText != null) {
124                                         // An invalid type that's not empty indicates that the primary key value has been created from a URL
125                                         // string. Use the same string to represent the primary key value on the URL.
126                                         primaryKeyValueString = urlText;
127                                         // TODO: Update the primary key value string with the actual Gda Value that was created. The primary
128                                         // key value could be different if the string-to-number conversion doesn't work.
129                                 }
130                                 break;
131
132                         default:
133                                 // Unknown types are represented in the URL by an empty string. When loading a page with an unknown from
134                                 // a URL (bookmark or link), the details view will run the query with an empty Value item based on the
135                                 // type from the Glom document. The first result from this query will be shown. This means that the
136                                 // specific record for unknown types are not bookmarkmarkable.
137
138                                 // Support for bookmarking a new type can be added by adding a case statement for the new type here
139                                 // and in this method:
140                                 // org.glom.web.server.Utils.getGlomTypeGdaValueForTypedDataItem()
141
142                                 // primaryKeyValueString remains empty
143                                 break;
144                         }
145
146                         return primaryKeyValueString;
147                 }
148
149                 /**
150                  * Create a DetailPlace that should be loaded from a URL string. This is called when users load the details view
151                  * directly with the URL string (a bookmark or link).
152                  * 
153                  * @see com.google.gwt.place.shared.PlaceTokenizer#getPlace(java.lang.String)
154                  * @see org.glom.web.server.Utils.getGlomTypeGdaValueForTypedDataItem(String, String, glom_field_type,
155                  *      TypedDataItem)
156                  */
157                 @Override
158                 public DetailsPlace getPlace(final String token) {
159                         // default empty values
160                         String documentID = "";
161                         String tableName = ""; // an empty value represents the default table
162
163                         final TypedDataItem primaryKeyValue = new TypedDataItem();
164
165                         final HashMap<String, String> params = getTokenParams(token);
166
167                         if (params == null) {
168                                 return new DetailsPlace("", "", primaryKeyValue);
169                         }
170
171                         if (params.get(documentKey) != null) {
172                                 documentID = params.get(documentKey);
173                         }
174
175                         if (params.get(tableKey) != null) {
176                                 tableName = params.get(tableKey);
177                         }
178
179                         if (params.get(primaryKeyValueKey) != null) {
180                                 final String primaryKeyValueString = params.get(primaryKeyValueKey);
181                                 // Set as unknown because the type of the primary key is not known at this point. A proper primary key
182                                 // value will be created using the type from the Glom document in the servlet.
183                                 primaryKeyValue.setUnknown(primaryKeyValueString);
184                         }
185
186                         if (StringUtils.isEmpty(documentID)) {
187                                 // The documentID was not retrieved from the URL. Use empty values for the details place.
188                                 return new DetailsPlace("", "", primaryKeyValue);
189                         }
190
191                         return new DetailsPlace(documentID, tableName, primaryKeyValue);
192                 }
193         }
194
195 }