blob: f52f120c321723539f9669c88ca01dae2fbcbe63 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.svn.commandLine;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 1/27/12
* Time: 1:00 PM
*/
public class SvnInfoHandler extends DefaultHandler {
@Nullable private final File myBase;
private final Consumer<SVNInfo> myInfoConsumer;
private Map<File, SVNInfo> myResultsMap;
private SvnInfoStructure myPending;
private final Map<String, Getter<ElementHandlerBase>> myElementsMap;
private final List<ElementHandlerBase> myParseStack;
private final StringBuilder mySb;
public SvnInfoHandler(@Nullable File base, final Consumer<SVNInfo> infoConsumer) {
myBase = base;
myInfoConsumer = infoConsumer;
myPending = createPending();
myElementsMap = new HashMap<String, Getter<ElementHandlerBase>>();
fillElements();
myParseStack = new ArrayList<ElementHandlerBase>();
myParseStack.add(new Fake());
myResultsMap = new HashMap<File, SVNInfo>();
mySb = new StringBuilder();
}
private void switchPending() throws SAXException {
final SVNInfo info;
try {
info = myPending.convert();
}
catch (SVNException e) {
throw new SAXException(e);
}
if (myInfoConsumer != null) {
myInfoConsumer.consume(info);
}
myResultsMap.put(info.getFile(), info);
myPending = createPending();
}
private SvnInfoStructure createPending() {
SvnInfoStructure pending = new SvnInfoStructure();
pending.myDepth = SVNDepth.INFINITY;
return pending;
}
@Override
public void endDocument() throws SAXException {
assertSAX(! myParseStack.isEmpty());
for (int i = myParseStack.size() - 1; i >= 0; -- i) {
ElementHandlerBase current = myParseStack.get(i);
if (current instanceof Entry) {
switchPending();
break;
}
}
myParseStack.clear();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
assertSAX(! myParseStack.isEmpty());
ElementHandlerBase current = myParseStack.get(myParseStack.size() - 1);
while (true) {
final boolean createNewChild = current.startElement(uri, localName, qName, attributes);
if (createNewChild) {
assertSAX(myElementsMap.containsKey(qName));
final ElementHandlerBase newChild = myElementsMap.get(qName).get();
newChild.setParent(current);
newChild.updateInfo(attributes, myPending);
myParseStack.add(newChild);
return;
} else {
// go up
if (current instanceof Entry) {
switchPending();
}
myParseStack.remove(myParseStack.size() - 1);
assertSAX(! myParseStack.isEmpty());
current = myParseStack.get(myParseStack.size() - 1);
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
ElementHandlerBase current = myParseStack.get(myParseStack.size() - 1);
String value = mySb.toString().trim();
if (!StringUtil.isEmpty(value)) {
current.characters(value, myPending);
}
mySb.setLength(0);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
assertSAX(! myParseStack.isEmpty());
mySb.append(ch, start, length);
}
public Map<String, Getter<ElementHandlerBase>> getElementsMap() {
return myElementsMap;
}
private void fillElements() {
myElementsMap.put("copy-from-url", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new CopyFromUrl();
}
});
myElementsMap.put("copy-from-rev", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new CopyFromRev();
}
});
myElementsMap.put("changelist", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new ChangeList();
}
});
myElementsMap.put("author", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Author();
}
});
myElementsMap.put("checksum", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Checksum();
}
});
myElementsMap.put("commit", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Commit();
}
});
myElementsMap.put("conflict", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Conflict();
}
});
myElementsMap.put("cur-base-file", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new CurBase();
}
});
myElementsMap.put("date", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Date();
}
});
myElementsMap.put("depth", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Depth();
}
});
myElementsMap.put("entry", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Entry(myBase);
}
});
myElementsMap.put("info", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Info();
}
});
myElementsMap.put("prev-base-file", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new PrevBase();
}
});
myElementsMap.put("prev-wc-file", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new PrevWc();
}
});
myElementsMap.put("prop-file", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new PropFile();
}
});
myElementsMap.put("repository", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Repository();
}
});
myElementsMap.put("root", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Root();
}
});
myElementsMap.put("schedule", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Schedule();
}
});
myElementsMap.put("text-updated", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new TextUpdated();
}
});
myElementsMap.put("tree-conflict", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new TreeConflict();
}
});
myElementsMap.put("url", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Url();
}
});
myElementsMap.put("relative-url", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new RelativeUrl();
}
});
myElementsMap.put("lock", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Lock();
}
});
myElementsMap.put("token", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new LockToken();
}
});
myElementsMap.put("owner", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new LockOwner();
}
});
myElementsMap.put("comment", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new LockComment();
}
});
myElementsMap.put("created", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new LockCreated();
}
});
myElementsMap.put("uuid", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Uuid();
}
});
myElementsMap.put("version", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new Version();
}
});
myElementsMap.put("wc-info", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new WcInfo();
}
});
myElementsMap.put("moved-to", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new MovedPath();
}
});
myElementsMap.put("moved-from", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new MovedPath();
}
});
myElementsMap.put("wcroot-abspath", new Getter<ElementHandlerBase>() {
@Override
public ElementHandlerBase get() {
return new WcRoot();
}
});
}
public Map<File, SVNInfo> getResultsMap() {
return myResultsMap;
}
private static void assertSAX(final boolean shouldBeTrue) throws SAXException {
if (! shouldBeTrue) {
throw new SAXException("can not parse output");
}
}
private static class Version extends ElementHandlerBase {
private Version() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
// TODO: Currently information for conflict (not tree-conflict) available in svn 1.8 is not used
// TODO: And it also not suite well for SVNKit api
if (getParent() instanceof Conflict) {
return;
}
final String side = attributes.getValue("side");
if ("source-left".equals(side)) {
final SvnInfoStructure.ConflictVersion conflictVersion = new SvnInfoStructure.ConflictVersion();
structure.myTreeConflict.mySourceLeft = conflictVersion;
setConflictFields(attributes, conflictVersion);
} else if ("source-right".equals(side)) {
final SvnInfoStructure.ConflictVersion conflictVersion = new SvnInfoStructure.ConflictVersion();
structure.myTreeConflict.mySourceRight = conflictVersion;
setConflictFields(attributes, conflictVersion);
}
}
private void setConflictFields(Attributes attributes, SvnInfoStructure.ConflictVersion conflictVersion) {
conflictVersion.myKind = attributes.getValue("kind");
conflictVersion.myPathInRepo = attributes.getValue("path-in-repos");
conflictVersion.myRepoUrl = attributes.getValue("repos-url");
conflictVersion.myRevision = attributes.getValue("revision");
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class TreeConflict extends ElementHandlerBase {
private TreeConflict() {
super(new String[]{}, new String[]{"version"});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
final SvnInfoStructure.TreeConflictDescription d = new SvnInfoStructure.TreeConflictDescription();
structure.myTreeConflict = d;
final String operation = attributes.getValue("operation");
if (! StringUtil.isEmptyOrSpaces(operation)) {
d.myOperation = operation;
}
final String kind = attributes.getValue("kind");
if (! StringUtil.isEmptyOrSpaces(kind)) {
d.myKind = kind;
}
final String reason = attributes.getValue("reason");
if (! StringUtil.isEmptyOrSpaces(reason)) {
d.myReason = reason;
}
final String victim = attributes.getValue("victim");
if (! StringUtil.isEmptyOrSpaces(victim)) {
d.myVictim = victim;
}
final String action = attributes.getValue("action");
if (! StringUtil.isEmptyOrSpaces(action)) {
d.myAction = action;
}
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class PropFile extends ElementHandlerBase {
private PropFile() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
// todo check whether base should be added
structure.myPropRejectFile = s;
}
}
private static class CurBase extends ElementHandlerBase {
private CurBase() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myConflictNew = new File(s).getName();
}
}
private static class PrevWc extends ElementHandlerBase {
private PrevWc() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myConflictWorking = new File(s).getName();
}
}
private static class PrevBase extends ElementHandlerBase {
private PrevBase() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myConflictOld = new File(s).getName();
}
}
private static class Conflict extends ElementHandlerBase {
private Conflict() {
super(new String[]{"prev-base-file","prev-wc-file","cur-base-file","prop-file"}, new String[]{"version"});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class Date extends ElementHandlerBase {
private Date() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
final SVNDate date = SVNDate.parseDate(s);
structure.myCommittedDate = date;
}
}
private static class Author extends ElementHandlerBase {
private Author() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myAuthor = s;
}
}
private static class Commit extends ElementHandlerBase {
private Commit() {
super(new String[]{"author","date"}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
final String revision = attributes.getValue("revision");
try {
final long number = Long.parseLong(revision);
structure.myCommittedRevision = number;
} catch (NumberFormatException e) {
throw new SAXException(e);
}
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class Checksum extends ElementHandlerBase {
private Checksum() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myChecksum = s;
}
}
/**
* "moved-from" and "moved-to" elements are represented by this class.
*/
private static class MovedPath extends ElementHandlerBase {
private MovedPath() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
// TODO: is there some field to initialize from this value?
}
}
private static class TextUpdated extends ElementHandlerBase {
private TextUpdated() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
final SVNDate date = SVNDate.parseDate(s);
structure.myTextTime = date;
}
}
private static class Depth extends ElementHandlerBase {
private Depth() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myDepth = SVNDepth.fromString(s);
}
}
private static class Schedule extends ElementHandlerBase {
private Schedule() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.mySchedule = s;
}
}
private static class WcRoot extends ElementHandlerBase {
private WcRoot() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
// there is no such thing???
}
}
private static class ChangeList extends ElementHandlerBase {
private ChangeList() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myChangelistName = s;
}
}
private static class CopyFromUrl extends ElementHandlerBase {
private CopyFromUrl() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
try {
structure.myCopyFromURL = SVNURL.parseURIEncoded(s);
}
catch (SVNException e) {
throw new SAXException(e);
}
}
}
private static class CopyFromRev extends ElementHandlerBase {
private CopyFromRev() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
try {
final long number = Long.parseLong(s);
structure.myCopyFromRevision = number;
} catch (NumberFormatException e) {
throw new SAXException(e);
}
}
}
private static class WcInfo extends ElementHandlerBase {
private WcInfo() {
super(new String[]{"wcroot-abspath", "schedule", "depth", "text-updated", "checksum", "changelist", "copy-from-url",
"copy-from-rev", "moved-to", "moved-from"}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class Uuid extends ElementHandlerBase {
private Uuid() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myUuid = s;
}
}
private static class Root extends ElementHandlerBase {
private Root() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
try {
structure.myRootURL = SVNURL.parseURIEncoded(s);
}
catch (SVNException e) {
throw new SAXException(e);
}
}
}
private static class Repository extends ElementHandlerBase {
private Repository() {
super(new String[]{"root", "uuid"}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class Url extends ElementHandlerBase {
private Url() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
try {
structure.myUrl = SVNURL.parseURIEncoded(s);
}
catch (SVNException e) {
throw new SAXException(e);
}
}
}
private static class RelativeUrl extends Url{
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.relativeUrl = s;
}
}
private static class Lock extends ElementHandlerBase {
private Lock() {
super(new String[]{"token", "owner", "comment", "created"}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
structure.myLockWrapper = new SVNLockWrapper();
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
}
}
private static class LockToken extends ElementHandlerBase {
private LockToken() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myLockWrapper.setID(s);
}
}
private static class LockOwner extends ElementHandlerBase {
private LockOwner() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myLockWrapper.setOwner(s);
}
}
private static class LockComment extends ElementHandlerBase {
private LockComment() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myLockWrapper.setComment(s);
}
}
private static class LockCreated extends ElementHandlerBase {
private LockCreated() {
super(new String[]{}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
}
@Override
public void characters(String s, SvnInfoStructure structure) throws SAXException {
structure.myLockWrapper.setCreationDate(SVNDate.parseDate(s));
}
}
private static class Entry extends ElementHandlerBase {
@Nullable private final File myBase;
private Entry(@Nullable final File base) {
super(new String[]{"url", "relative-url", "lock", "repository","wc-info","commit","conflict","tree-conflict"}, new String[]{});
myBase = base;
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException {
final String kind = attributes.getValue("kind");
assertSAX(! StringUtil.isEmptyOrSpaces(kind));
structure.myKind = SVNNodeKind.parseKind(kind);
if (myBase != null) {
final String path = attributes.getValue("path");
assertSAX(!StringUtil.isEmptyOrSpaces(path));
structure.myFile = new File(myBase, path);
}
final String revision = attributes.getValue("revision");
assertSAX(! StringUtil.isEmptyOrSpaces(revision));
try {
final long number = Long.parseLong(revision);
structure.myRevision = number;
} catch (NumberFormatException e) {
structure.myRevision = -1;
//throw new SAXException(e);
}
}
@Override
public void characters(String s, SvnInfoStructure structure) {
}
}
private static class Info extends ElementHandlerBase {
private Info() {
super(new String[]{}, new String[]{"entry"});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) {
}
@Override
public void characters(String s, SvnInfoStructure structure) {
}
}
private static class Fake extends ElementHandlerBase {
private Fake() {
super(new String[]{"info"}, new String[]{});
}
@Override
protected void updateInfo(Attributes attributes, SvnInfoStructure structure) {
}
@Override
public void characters(String s, SvnInfoStructure structure) {
}
}
private abstract static class ElementHandlerBase {
private final Set<String> myAwaitedChildren;
private final Set<String> myAwaitedChildrenMultiple;
private ElementHandlerBase parent;
ElementHandlerBase(String[] awaitedChildren, String[] awaitedChildrenMultiple) {
myAwaitedChildren = new HashSet<String>(Arrays.asList(awaitedChildren));
myAwaitedChildrenMultiple = new HashSet<String>(Arrays.asList(awaitedChildrenMultiple));
}
@NotNull
public ElementHandlerBase getParent() {
return parent;
}
public void setParent(@NotNull ElementHandlerBase parent) {
this.parent = parent;
}
protected abstract void updateInfo(Attributes attributes, SvnInfoStructure structure) throws SAXException;
public boolean startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (myAwaitedChildrenMultiple.contains(qName)) {
return true;
}
return myAwaitedChildren.remove(qName);
}
public abstract void characters(String s, SvnInfoStructure structure) throws SAXException;
}
}