/* * File : JClicProject.java * Created : 16-aug-2001 1:17 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details (see the LICENSE file). */ package edu.xtec.jclic.project; import edu.xtec.jclic.PlayStation; import edu.xtec.jclic.bags.*; import edu.xtec.jclic.edit.Editable; import edu.xtec.jclic.edit.Editor; import edu.xtec.jclic.fileSystem.FileSystem; import edu.xtec.jclic.fileSystem.ZipFileSystem; import edu.xtec.jclic.media.EventSounds; import edu.xtec.jclic.skins.Skin; import edu.xtec.util.Domable; import edu.xtec.util.JDomUtility; import edu.xtec.util.ProgressDialog; import edu.xtec.util.ResourceBridge; import edu.xtec.util.StrUtils; import java.io.*; import java.util.*; import java.util.zip.*; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.09 */ public class JClicProject extends Object implements Editable, Domable { public static String CURRENT_VERSION="0.1.3"; protected ResourceBridge bridge; protected FileSystem fileSystem; public ActivityBag activityBag; public ActivitySequence activitySequence; public MediaBag mediaBag; public Skin skin; protected String name; public String version; public ProjectSettings settings; public String type; /** Optional code used in reports for filtering queries by activity */ public String code; protected String fullPath; public static String TYPE="type"; /** Creates new JClicProject */ public JClicProject(ResourceBridge bridge, FileSystem fileSystem, String fullPath) { this.fileSystem=fileSystem; this.bridge=bridge; this.fullPath = (fullPath==null ? "" : fullPath); version=CURRENT_VERSION; settings=new ProjectSettings(); settings.title=bridge.getMsg("UNNAMED"); setName(settings.title); type=null; activityBag=new ActivityBag(this); activitySequence=new ActivitySequence(this); mediaBag=new MediaBag(this/*, fileSystem*/); skin=null; } public static String ELEMENT_NAME="JClicProject"; public static String VERSION="version", NAME="name", CODE="code"; public org.jdom.Element getJDomElement(){ org.jdom.Element e=new org.jdom.Element(ELEMENT_NAME); //if(settings.title==ProjectSettings.UNTITLED && name!=NO_NAME) // settings.title=name; e.setAttribute(NAME, name); e.setAttribute(VERSION, CURRENT_VERSION); if(type!=null) e.setAttribute(TYPE, type); if(code!=null) e.setAttribute(CODE, code); e.addContent(settings.getJDomElement()); e.addContent(activitySequence.getJDomElement()); e.addContent(activityBag.getJDomElement()); e.addContent(mediaBag.getJDomElement()); return e; } //public void load(org.jdom.Element e) throws Exception{ // setProperties(e, null); //} public void setProperties(org.jdom.Element e, Object aux) throws Exception{ JDomUtility.checkName(e, ELEMENT_NAME); org.jdom.Element child; name=JDomUtility.getStringAttr(e, NAME, name, false); version=JDomUtility.getStringAttr(e, VERSION, version, false); type=JDomUtility.getStringAttr(e, TYPE, type, false); code=JDomUtility.getStringAttr(e, CODE, code, false); if((child=e.getChild(ProjectSettings.ELEMENT_NAME))!=null) settings=ProjectSettings.getProjectSettings(child); //if(settings.title==ProjectSettings.UNTITLED && name!=NO_NAME) // settings.title=name; //activitySequence.addElements(e.getChild(ActivitySequence.ELEMENT_NAME)); activitySequence.setProperties(e.getChild(ActivitySequence.ELEMENT_NAME), null); //activityBag.addActivities(e.getChild(ActivityBag.ELEMENT_NAME)); activityBag.setProperties(e.getChild(ActivityBag.ELEMENT_NAME), null); if(version.compareTo("0.1.2")<=0) activityBag.sortByName(); //mediaBag.addMediaElements(e.getChild(MediaBag.ELEMENT_NAME)); mediaBag.setProperties(e.getChild(MediaBag.ELEMENT_NAME), null); } public static JClicProject getJClicProject(org.jdom.Element e, ResourceBridge rb, FileSystem fs, String fullPath) throws Exception{ JClicProject jcp=new JClicProject(rb, fs, fullPath); //jcp.load(e); jcp.setProperties(e, null); return jcp; } public static JClicProject getJClicProject(ResourceBridge rb, String fullPath, ProgressDialog pd) throws Exception{ JClicProject result=null; if(pd!=null) pd.setText(rb.getMsg("msg_loading")+" "+fullPath); FileSystem fileSystem = FileSystem.createFileSystem(fullPath, rb); fullPath=fileSystem.getUrl(fullPath); if(fullPath.startsWith("file://")) fullPath=fullPath.substring(7); String projectName; if(fullPath.endsWith(".jclic.zip")){ fileSystem=FileSystem.createFileSystem(fullPath, rb); String[] projects=((ZipFileSystem)fileSystem).getEntries(".jclic"); if(projects==null) throw new Exception("File "+fullPath+" does not contain any jclic project"); projectName=projects[0]; } else{ fileSystem=new FileSystem(FileSystem.getPathPartOf(fullPath), rb); projectName=FileSystem.getFileNameOf(fullPath); } if(projectName.endsWith(".jclic")){ org.jdom.Document doc=fileSystem.getXMLDocument(projectName); System.gc(); result=getJClicProject(doc.getRootElement(), rb, fileSystem, fullPath); } if(result!=null){ result.mediaBag.waitForAllImages(); //System.gc(); } return result; } public org.jdom.Document getDocument(){ return new org.jdom.Document(getJDomElement()); } public void saveDocument(OutputStream out) throws Exception{ JDomUtility.saveDocument(out, getDocument()); } public void saveZipDocument(OutputStream out, boolean includeMedia) throws Exception{ ZipOutputStream zos=new ZipOutputStream(out); zos.putNextEntry(new ZipEntry(name+".jclic")); saveDocument(zos); zos.closeEntry(); if(includeMedia){ Set<String> set=Collections.synchronizedSet(new HashSet<String>()); Iterator<MediaBagElement> mbit=mediaBag.getElements().iterator(); while(mbit.hasNext()){ MediaBagElement mbe=mbit.next(); if(mbe.saveFlag){ String fName=mbe.getFileName(); if(fName!=null && fName.length()>0) set.add(fName); } } for (String fName : set) { zos.putNextEntry(new ZipEntry(fName)); zos.write(fileSystem.getBytes(fName)); zos.closeEntry(); } } zos.close(); out.close(); } public void saveZipDocumentPreservingZipContents(OutputStream out, ZipFileSystem zfs) throws Exception{ ZipOutputStream zos=new ZipOutputStream(out); zos.putNextEntry(new ZipEntry(name+".jclic")); saveDocument(zos); zos.closeEntry(); String[] entries=zfs.getEntries(null); if(entries!=null){ for(String entry : entries){ if(!entry.endsWith(".jclic")){ zos.putNextEntry(new ZipEntry(entry)); zos.write(zfs.getBytes(entry)); zos.closeEntry(); } } } zos.close(); out.close(); } public void saveProject(String fileName) throws Exception{ // Free discardable objects allocated in memory mediaBag.clearData(); System.runFinalization(); System.gc(); // ------------- String fn=fileSystem.getFullFileNamePath(fileName); FileOutputStream fos=fileSystem.createSecureFileOutputStream(fn); saveZipDocument(fos, true); fos.close(); setFileSystem(FileSystem.createFileSystem(fn, bridge)); setFullPath(fn); } public void setName(String newName){ int p; name=StrUtils.secureString(newName, bridge.getMsg("UNNAMED")); name=(new File(name)).getName(); if((p=name.indexOf('.'))>=0) name=name.substring(0, p); if(name.indexOf(' ')>=0) name=name.replace(' ', '_'); if(name.length()<1) name="NO_NAME"; } public String getName(){ return name; } public String getPublicName(){ /* String result=name; if("noName".equals(name) || bridge.getMsg("UNNAMED").equals(name)) result=settings.title; return result; */ return settings.title; } public void realize(EventSounds parent, PlayStation ps) { if(skin==null && settings.skinFileName!=null && settings.skinFileName.length()>0) skin=mediaBag.getSkinElement(settings.skinFileName, ps); if(settings.eventSounds!=null){ settings.eventSounds.setParent(parent); settings.eventSounds.realize(ps.getOptions(), mediaBag); } mediaBag.buildFonts(); } public void end(){ if(settings.eventSounds!=null){ settings.eventSounds.close(); settings.eventSounds=null; } mediaBag.clearData(); mediaBag.clear(); fileSystem.close(); System.gc(); } @Override protected void finalize() throws Throwable{ end(); super.finalize(); } /** Getter for property resourceBridge. * @return Value of property resourceBridge. */ public edu.xtec.util.ResourceBridge getBridge() { return bridge; } /** Setter for property bridge. * @param bridge New value of property {@link #bridge}. */ public void setBridge(edu.xtec.util.ResourceBridge bridge) { this.bridge = bridge; } /** Getter for property fileSystem. * @return Value of property fileSystem. */ public edu.xtec.jclic.fileSystem.FileSystem getFileSystem() { return fileSystem; } /** Setter for property fileSystem. * @param fileSystem New value of property fileSystem. */ public void setFileSystem(edu.xtec.jclic.fileSystem.FileSystem fileSystem) { if(this.fileSystem!=null && this.fileSystem!=fileSystem) this.fileSystem.close(); this.fileSystem = fileSystem; } /** Getter for property fullPath. * @return Value of property fullPath. */ public java.lang.String getFullPath() { return fullPath; } /** Setter for property fullPath. * @param fullPath New value of property fullPath. */ public void setFullPath(java.lang.String fullPath) { this.fullPath = fullPath; } public Editor getEditor(Editor parent) { return Editor.createEditor("edu.xtec.jclic.project.JClicProjectEditor", this, parent); //return Editor.createEditor(getClass().getName()+"Editor", this, parent); } }