View Javadoc

1   /***
2    * Created on Aug 4, 2005, Copyright UC Regents
3    */
4   package wise2.converter;
5   
6   import java.io.File;
7   import java.io.FileNotFoundException;
8   import java.io.FileOutputStream;
9   import java.io.IOException;
10  import java.io.InputStream;
11  import java.io.InputStreamReader;
12  import java.io.OutputStream;
13  import java.text.DecimalFormat;
14  import java.util.ArrayList;
15  import java.util.HashMap;
16  import java.util.List;
17  import java.util.Map;
18  import java.util.Set;
19  import java.util.Map.Entry;
20  import java.util.jar.JarOutputStream;
21  import java.util.zip.ZipEntry;
22  import java.util.zip.ZipFile;
23  
24  import javax.swing.JFileChooser;
25  import javax.swing.filechooser.FileFilter;
26  
27  import net.sf.sail.core.beans.Pod;
28  import net.sf.sail.core.entity.Rim;
29  import net.sf.sail.core.util.BinaryUtils;
30  import net.sf.sail.core.uuid.CurnitUuid;
31  import net.sf.sail.core.uuid.PodUuid;
32  
33  import org.dom4j.Document;
34  import org.dom4j.DocumentException;
35  import org.dom4j.Node;
36  import org.dom4j.io.SAXReader;
37  import org.doomdark.uuid.UUID;
38  import org.doomdark.uuid.UUIDGenerator;
39  
40  import org.telscenter.pas.beans.PasActivity;
41  import org.telscenter.pas.beans.PasProject;
42  import org.telscenter.pas.beans.PasStep;
43  import org.telscenter.pas.builders.AbstractPasBuilder;
44  
45  import wise2.converter.converters.UnsupportedConverter;
46  
47  /***
48   * Convert a wobnit to a curnit.
49   * 
50   * @author turadg
51   */
52  public class ProjectConverter {
53  
54  	static String POD_PRE = "dddddddd-6004-";
55  
56  	static String POD_POST = "-0000-000000000000";
57  
58  	private Map<Pod, JarOutputStream> podToArchive = new HashMap<Pod, JarOutputStream>() {
59  		/***
60  		 * Not intended to be serialized, just added remove compile warning
61  		 */
62  		private static final long serialVersionUID = 1L;
63  		
64  		@Override
65  		public JarOutputStream get(Object key) {
66  			Pod pod = (Pod) key;
67  			JarOutputStream archive = super.get(key);
68  			if (archive == null) {
69  				try {
70  					archive = BinaryUtils.newPodArchiveFor(pod);
71  					podToArchive.put(pod, archive);
72  				} catch (IOException e) {
73  					// TODO Auto-generated catch block
74  					e.printStackTrace();
75  				}
76  			}
77  			return archive;
78  		}
79  	};
80  
81  	private Document document;
82  
83  	private IProjectUploadProvider uploadProvider;
84  
85  	private PasProject project;
86  
87  	private boolean omitUnsupported;
88  
89  	public ProjectConverter(final ZipFile wobnitArchiveFile)
90  			throws DocumentException, IOException {
91  		ZipEntry entry = wobnitArchiveFile.getEntry("wise-project.xml");
92  		InputStream is = wobnitArchiveFile.getInputStream(entry);
93  		InputStreamReader xmlInput = new InputStreamReader(is, "UTF-8");
94  		SAXReader reader = new SAXReader();
95  		document = reader.read(xmlInput);
96  
97  		uploadProvider = new IProjectUploadProvider() {
98  			public InputStream getProjectUpload(String name) throws IOException {
99  				String entryPath = "upload/" + name;
100 				ZipEntry entry = wobnitArchiveFile.getEntry(entryPath);
101 				return wobnitArchiveFile.getInputStream(entry);
102 			}
103 		};
104 	}
105 
106 	private Pod makeProjectPod() throws FileNotFoundException, IOException,
107 			InstantiationException, IllegalAccessException {
108 		DecimalFormat df = new DecimalFormat("0000");
109 		String upper = df.format((getProjectId() / 10000) % 10000);
110 		String lower = df.format(getProjectId() % 10000);
111 	  
112 		String idStr = "cccccccc-" + upper + "-" + lower + "-0000-000000000000";
113 		
114 		PodUuid podId = new PodUuid(idStr);
115 		
116 		Pod projectPod = new Pod();
117 		projectPod.setPodId(podId);
118 
119 		project = ConverterFactory.createBeanInPod(projectPod,
120 				PasProject.class, getProjectTitle());
121 		
122 		// TODO: The following sequence should be replaced
123 		// by a more general way of binding rims at this level.
124 		// Right now, this is the only place that knows how
125 		// to create project level rims.
126 		Rim rim = new Rim();
127 		rim.setName("navigation_log");
128 		rim.setShape(String.class);
129 		project.setNavigationLogRim(rim);
130 		projectPod.add(rim);
131 		
132 		rim = new Rim();
133 		rim.setName("session_state");
134 		rim.setShape(String.class);
135 		project.setSessionStateRim(rim);
136 		projectPod.add(rim);
137 		
138 		rim = new Rim();
139 		rim.setName("curnit_map");
140 		rim.setShape(String.class);
141 		project.setCurnitMapRim(rim);
142 		projectPod.add(rim);
143 		
144 
145 		addActivities(projectPod, document);
146 
147 		return projectPod;
148 	}
149 
150 	/***
151 	 * @param projectPod
152 	 * @param project
153 	 * @throws IOException
154 	 * @throws FileNotFoundException
155 	 * @throws IllegalAccessException
156 	 * @throws InstantiationException
157 	 */
158 	@SuppressWarnings("unchecked")
159 	private void addActivities(Pod projectPod, Node projectNode)
160 			throws FileNotFoundException, IOException, InstantiationException,
161 			IllegalAccessException {
162 		List<PasActivity> activityList = new ArrayList<PasActivity>();
163 		List<Node> activityTitleNodes = projectNode.selectNodes("//activity");
164 		int acIndex = 0;
165 		for (Node activityModelNode : activityTitleNodes) {
166 			String activityTitle = activityModelNode.selectSingleNode("title")
167 					.getText();
168 			Pod acPod = AbstractPasBuilder.nextPod(POD_PRE, POD_POST);
169 			PasActivity activity = ConverterFactory.createBeanInPod(acPod,
170 					PasActivity.class, activityTitle);
171 			activityList.add(activity);
172 			addSteps(acPod, activityModelNode, activity);
173 			AbstractPasBuilder.addActivity(projectPod, acIndex, acPod);
174 			acIndex += 1;
175 //			BinaryUtils.cleanClosePodArchive(acPod, podToArchive.get(acPod));
176 		}
177 		
178 		Set<Entry<Pod, JarOutputStream>> entries = podToArchive.entrySet();
179 		for(Entry<Pod, JarOutputStream> entry: entries){
180 			BinaryUtils.cleanClosePodArchive(entry.getKey(), entry.getValue());
181 		}
182 		PasActivity[] activities = activityList
183 				.toArray(new PasActivity[activityList.size()]);
184 		project.setActivities(activities);
185 	}
186 
187 	/***
188 	 * @param podArchiveOut
189 	 * @param activityModelNode
190 	 * @param activity
191 	 */
192 	@SuppressWarnings("unchecked")
193 	private void addSteps(Pod activityPod, Node activityModelNode,
194 			PasActivity activity) {
195 		int stepIndex = 0;
196 		List<Node> stepNodes = activityModelNode.selectNodes("step");
197 		for (Node stepNode : stepNodes) {
198 			Node typeNode = stepNode.selectSingleNode("type");
199 			String stepType = (typeNode == null) ? "Unspecified" : typeNode
200 					.getText();
201 			AbstractStepConverter converter = ConverterFactory
202 					.converterClass(stepType);
203 			if (converter instanceof UnsupportedConverter && omitUnsupported)
204 				continue;
205 			Pod stepPod = AbstractPasBuilder.nextPod(POD_PRE, POD_POST);
206 			converter.setPod(stepPod);
207 			converter.setPodArchiveOutputStream(podToArchive.get(stepPod));
208 			converter.setStepNode(stepNode);
209 			converter.setUploadProvider(uploadProvider);
210 
211 			PasStep step = converter.getPasStep();
212 			stepPod.add(step);
213 
214 			AbstractPasBuilder.addStep(activityPod, stepIndex, stepPod);
215 			stepIndex += 1;
216 		}
217 	}
218 
219 	private String getProjectTitle() {
220 		return document.selectSingleNode("/wise-project/title").getText();
221 	}
222 
223 	private int getProjectId() {
224 		String projectIdStr = document.selectSingleNode(
225 				"/wise-project/projectID").getText();
226 		return Integer.valueOf(projectIdStr);
227 	}
228 
229 	public void writeCurnit(OutputStream out) throws IOException {
230 		UUID timeId = UUIDGenerator.getInstance().generateTimeBasedUUID();
231 		CurnitUuid cid = new CurnitUuid(timeId.asByteArray());
232 		try {
233 			AbstractPasBuilder.writeCurnit(cid, getProjectTitle(),
234 					makeProjectPod(), out);
235 		} catch (Exception e) {
236 			e.printStackTrace();
237 			throw new IOException("Error writing curnit: " + e);
238 		}
239 	}
240 
241 	/***
242 	 * @param args
243 	 * @throws IOException
244 	 */
245 	static File chooseProjectArchiveFile(String[] args) throws IOException {
246 		if (args.length == 0) {
247 			final JFileChooser fc = new JFileChooser("target");
248 
249 			fc.setFileFilter(new FileFilter() {
250 				@Override
251 				public boolean accept(File file) {
252 					String name = file.getName();
253 					if (name.endsWith("-wpe.jar"))
254 						return true;
255 					if (file.isDirectory())
256 						return true;
257 					return false;
258 				}
259 
260 				@Override
261 				public String getDescription() {
262 					return "WISE project export";
263 				}
264 			});
265 
266 			int returnVal = fc.showOpenDialog(null);
267 
268 			if (returnVal != JFileChooser.APPROVE_OPTION)
269 				return null;
270 
271 			return fc.getSelectedFile();
272 		}
273 
274 		// there is an argument
275 		return new File(args[0]);
276 	}
277 
278 	public static void main(String[] args) throws Exception {
279 		File projectArchiveFile = chooseProjectArchiveFile(args);
280 
281 		ProjectConverter pc = new ProjectConverter(new ZipFile(
282 				projectArchiveFile));
283 		File outPath = new File("target/converted-" + pc.getProjectId()
284 				+ ".jar");
285 		pc.writeCurnit(new FileOutputStream(outPath));
286 		System.out.println("written to " + outPath.getAbsolutePath());
287 		System.exit(0);
288 	}
289 
290 	public void setOmitUnsupportedSteps(boolean omitUnsupportedSteps) {
291 		omitUnsupported = omitUnsupportedSteps;
292 	}
293 
294 }