DetailsActivity: Check for authentication here too.
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / server / Utils.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.server;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.text.ParseException;
29 import java.text.SimpleDateFormat;
30 import java.util.Date;
31
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.http.client.utils.URIBuilder;
34 import org.glom.web.shared.TypedDataItem;
35 import org.glom.web.shared.libglom.Field.GlomFieldType;
36 import org.glom.web.shared.libglom.layout.LayoutItemField;
37
38 /**
39  *
40  */
41 public class Utils {
42
43         /*
44          * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
45          * 
46          * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
47          */
48         public static int safeLongToInt(final long value) {
49                 if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
50                         throw new IllegalArgumentException(value + " cannot be cast to int without changing its value.");
51                 }
52                 return (int) value;
53         }
54
55         public static String getFileName(final String fileURI) {
56                 final String[] splitURI = fileURI.split(File.separator);
57                 return splitURI[splitURI.length - 1];
58         }
59
60         static public Object deepCopy(final Object oldObj) {
61                 ObjectOutputStream oos = null;
62                 ObjectInputStream ois = null;
63
64                 try {
65                         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
66                         oos = new ObjectOutputStream(bos);
67                         // serialize and pass the object
68                         oos.writeObject(oldObj);
69                         oos.flush();
70                         final ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
71                         ois = new ObjectInputStream(bin);
72
73                         // return the new object
74                         return ois.readObject();
75                 } catch (final Exception e) {
76                         System.out.println("Exception in deepCopy:" + e);
77                         return null;
78                 } finally {
79                         try {
80                                 oos.close();
81                                 ois.close();
82                         } catch (final IOException e) {
83                                 System.out.println("Exception in deepCopy during finally: " + e);
84                                 return null;
85                         }
86                 }
87         }
88
89         /** Build the URL for the service that will return the binary data for an image.
90          * 
91          * @param primaryKeyValue
92          * @param field
93          * @return
94          */
95         public static String buildImageDataUrl(final TypedDataItem primaryKeyValue, final String documentID, final String tableName, final LayoutItemField field) {
96                 final URIBuilder uriBuilder = buildImageDataUrlStart(documentID, tableName);
97                 
98                 //TODO: Handle other types:
99                 if(primaryKeyValue != null) {
100                         uriBuilder.setParameter("value", Double.toString(primaryKeyValue.getNumber()));
101                 }
102                 
103                 uriBuilder.setParameter("field", field.getName());
104                 return uriBuilder.toString();
105         }
106
107         /** Build the URL for the service that will return the binary data for an image.
108          * 
109          * @param primaryKeyValue
110          * @param field
111          * @return
112          */
113         public static String buildImageDataUrl(final String documentID, final String tableName, final String layoutName, final int[] path) {
114                 final URIBuilder uriBuilder = buildImageDataUrlStart(documentID, tableName);
115                 uriBuilder.setParameter("layout", layoutName);
116                 uriBuilder.setParameter("layoutpath", buildLayoutPath(path));
117                 return uriBuilder.toString();
118         }
119
120         /**
121          * @param documentID
122          * @param tableName
123          * @return
124          */
125         private static URIBuilder buildImageDataUrlStart(final String documentID, final String tableName) {
126                 final URIBuilder uriBuilder = new URIBuilder();
127                 //uriBuilder.setHost(GWT.getModuleBaseURL());
128                 uriBuilder.setPath("OnlineGlom/gwtGlomImages"); //The name of our images servlet. See OnlineGlomImages.
129                 uriBuilder.setParameter("document", documentID);
130                 uriBuilder.setParameter("table", tableName);
131                 return uriBuilder;
132         }
133
134         /** Build a :-separated string to represent the path as a string.
135          * @param path
136          * @return
137          */
138         public static String buildLayoutPath(int[] path) {
139                 if((path == null) || (path.length == 0)) {
140                         return null;
141                 }
142
143                 String result = new String();
144                 for(int i:path) {
145                         if(!result.isEmpty()) {
146                                 result += ":";
147                         }
148                         
149                         final String strIndex = Integer.toString(i);
150                         result += strIndex;
151                 }
152                 
153                 return result;
154         }
155
156         /** Get an array of int indices from the :-separated string.
157          * See buildLayoutPath().
158          * 
159          * @param attrLayoutPath
160          * @return The array of indices of the layout items.
161          */
162         public static int[] parseLayoutPath(final String attrLayoutPath) {
163                 if(StringUtils.isEmpty(attrLayoutPath)) {
164                         return null;
165                 }
166                 
167                 final String[] strIndices = attrLayoutPath.split(":");
168                 final int[] indices = new int[strIndices.length];
169                 for (int i = 0; i < strIndices.length; ++i) {
170                         final String str = strIndices[i];
171         
172                         try
173                         {
174                                 indices[i] = Integer.parseInt(str);
175                         }
176                         catch (final NumberFormatException nfe)
177                         {
178                                 //TODO: Log the error.
179                                 return null;
180                         }
181                 }
182         
183                 return indices;
184         }
185
186         public static void transformUnknownToActualType(final TypedDataItem dataItem, final GlomFieldType actualType) {
187                 if(dataItem.getType() == actualType)
188                         return;
189                 
190                 String unknownText = dataItem.getUnknown();
191                 
192                 //Avoid repeated checks for null:
193                 if (unknownText == null) {
194                         unknownText = "";
195                 }
196         
197                 switch(actualType) {
198                 case TYPE_NUMERIC:
199                         // TODO: Is this really locale-independent?
200                         final double number = Double.parseDouble(unknownText);          
201                         dataItem.setNumber(number);
202                         break;
203                 case TYPE_TEXT:
204                         dataItem.setText(unknownText);
205                         break;
206                 case TYPE_DATE:
207                         final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
208                 Date date = null;
209                         try {
210                                 date = formatter.parse(unknownText);
211                         } catch (ParseException e) {
212                                 // TODO Auto-generated catch block
213                                 e.printStackTrace();
214                         }
215         
216                         dataItem.setDate(date); 
217                         break;
218                 case TYPE_TIME:
219                         /*TODO :
220                         SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
221                 Date date;
222                         try {
223                                 date = formatter.parse(unknownText);
224                         } catch (ParseException e) {
225                                 // TODO Auto-generated catch block
226                                 e.printStackTrace();
227                         }
228         
229                         setDate(date); 
230                         */
231                         break;
232                 case TYPE_BOOLEAN:
233                         final boolean bool = unknownText.equals("true");
234                         dataItem.setBoolean(bool); //TODO
235                         break;
236                 case TYPE_IMAGE:
237                         dataItem.setImageDataUrl(unknownText);
238                         //setImageData(null);//TODO: Though this is only used for primary keys anyway.
239                         break;
240                 case TYPE_INVALID:
241                         break;
242                 default:
243                         break; //TODO: Warn because this is unusual?
244                 }
245         }
246
247 }