package org.dodgybits.shuffle.android.synchronisation.tracks; import java.io.IOException; import java.io.StringWriter; import java.text.ParseException; import java.util.Map; import org.dodgybits.android.shuffle.R; import org.dodgybits.shuffle.android.core.model.EntityBuilder; import org.dodgybits.shuffle.android.core.model.Id; import org.dodgybits.shuffle.android.core.model.Project; import org.dodgybits.shuffle.android.core.model.Project.Builder; import org.dodgybits.shuffle.android.core.model.persistence.EntityPersister; import org.dodgybits.shuffle.android.core.util.DateUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.text.TextUtils; import android.util.Log; import android.util.Xml; /** * @author Morten Nielsen */ public final class ProjectSynchronizer extends Synchronizer<Project> { private static final String cTag = "ProjectSynchronizer"; private final String mTracksUrl; public ProjectSynchronizer( EntityPersister<Project> persister, TracksSynchronizer tracksSynchronizer, WebClient client, android.content.Context context, int basePercent, String tracksUrl) { super(persister, tracksSynchronizer, client, context, basePercent); mTracksUrl = tracksUrl; } @Override protected void verifyLocalEntities(Map<Id, Project> localEntities) { } @Override protected EntityBuilder<Project> createBuilder() { return Project.newBuilder(); } @Override protected String readingRemoteText() { return mContext.getString(R.string.readingRemoteContexts); } @Override protected String processingText() { return mContext.getString(R.string.processingProjects); } @Override protected String readingLocalText() { return mContext.getString(R.string.readingLocalProjects); } @Override protected String stageFinishedText() { return mContext.getString(R.string.doneWithProjects); } protected Project createMergedLocalEntity(Project localProject, Project remoteProject) { Builder builder = Project.newBuilder(); builder.mergeFrom(localProject); builder .setName(remoteProject.getName()) .setModifiedDate(remoteProject.getModifiedDate()) .setArchived(remoteProject.isArchived()) .setDefaultContextId(remoteProject.getDefaultContextId()) .setTracksId(remoteProject.getTracksId()); return builder.build(); } protected String createDocumentForEntity(Project project) { XmlSerializer serializer = Xml.newSerializer(); StringWriter writer = new StringWriter(); try { serializer.setOutput(writer); String now = DateUtils.formatIso8601Date(System.currentTimeMillis()); serializer.startTag("", "project"); serializer.startTag("", "created-at").attribute("", "type", "datetime").text(now).endTag("", "created-at"); Id contextId = findTracksIdByContextId(project.getDefaultContextId()); if(contextId.isInitialised()) { serializer.startTag("", "default-context-id").attribute("", "type", "integer").text(contextId.toString()).endTag("", "default-context-id"); } serializer.startTag("", "name").text(project.getName()).endTag("", "name"); serializer.startTag("", "state").text(project.isArchived() ? "hidden": "active").endTag("", "state"); serializer.startTag("", "updated-at").attribute("", "type", "datetime").text(now).endTag("", "updated-at"); serializer.endTag("", "project"); serializer.flush(); } catch (IOException ignored) { Log.d(cTag, "Failed to serialize project", ignored); } return writer.toString(); } protected Project parseSingleEntity(XmlPullParser parser) throws ParseException { Builder builder = Project.newBuilder(); Project project = null; try { int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT && project == null) { String name = parser.getName(); switch (eventType) { case XmlPullParser.START_TAG: if (name.equalsIgnoreCase("name")) { builder.setName(parser.nextText()); } else if (name.equalsIgnoreCase("id")) { Id tracksId = Id.create(Long.parseLong(parser.nextText())); builder.setTracksId(tracksId); } else if (name.equalsIgnoreCase("updated-at")) { String dateStr = parser.nextText(); long modifiedDate = DateUtils.parseIso8601Date(dateStr); builder.setModifiedDate(modifiedDate); } else if (name.equalsIgnoreCase("default-context-id")) { String tokenValue = parser.nextText(); if (!TextUtils.isEmpty(tokenValue)) { Id tracksId = Id.create(Long.parseLong(tokenValue)); Id defaultContextId = findContextIdByTracksId(tracksId); if (defaultContextId.isInitialised()) { builder.setDefaultContextId(defaultContextId); } } } else if (name.equalsIgnoreCase("state")) { boolean archived = !parser.nextText().equalsIgnoreCase("active"); builder.setArchived(archived); } break; case XmlPullParser.END_TAG: if (name.equalsIgnoreCase("project")) { project = builder.build(); } break; } eventType = parser.next(); } } catch (IOException e) { throw new ParseException("Unable to parse project:" + e.getMessage(), 0); } catch (XmlPullParserException e) { throw new ParseException("Unable to parse project:" + e.getMessage(), 0); } return project; } @Override protected String createEntityUrl(Project project) { return mTracksUrl+ "/projects/" + project.getTracksId().getId() + ".xml"; } @Override protected String endIndexTag() { return "projects"; } @Override protected String entityIndexUrl() { return mTracksUrl+ "/projects.xml"; } }