/
Libra
/
my-application
Обзор
Документация
Войти
/
Libra
/
my-application
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
app/src/main/java/com/libraprogramming/myapplication/service/XmlFileCardsImportService.java
258 строк
9 KB
Толмачёв Владимир Викторович
Architecture refactoring 2
20 июл 2026, 17:22
20 июл 2026, 17:22
87aa6f2
Код
Авторство
О чём код?
package com.libraprogramming.myapplication.service; import android.content.Context; import android.net.Uri; import android.util.Xml; import androidx.annotation.NonNull; import com.libraprogramming.domain.exception.CardsImportException; import com.libraprogramming.domain.model.Card; import com.libraprogramming.domain.model.CodeFormat; import com.libraprogramming.domain.repository.CardRepository; import com.libraprogramming.domain.service.CardsImportService; import org.jetbrains.annotations.NotNull; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import javax.inject.Inject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; public class XmlFileCardsImportService extends XmlCardsService implements CardsImportService { @NotNull private final Context context; @NonNull private final CardRepository repository; private static final String TAG = XmlFileCardsImportService.class.getSimpleName(); @Inject public XmlFileCardsImportService( @NotNull Context context, @NonNull CardRepository repository) { this.context = context; this.repository = repository; } @Override public void importCards(Uri targetUri) throws CardsImportException { try (final InputStream stream = context.getContentResolver().openInputStream(Objects.requireNonNull(targetUri)); final var reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { final var parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); parser.setInput(reader); parser.nextTag(); parser.require(XmlPullParser.START_TAG, null, Constant.ROOT_ELEMENT); final List<ImportingCard> cards = parserLoyaltyCards(parser); if (cards != null && !cards.isEmpty()) { applyCards(cards); } parser.require(XmlPullParser.END_TAG, null, Constant.ROOT_ELEMENT); } catch (XmlPullParserException exception) { throw new CardsImportException("Error reading file", exception); } catch (IOException exception) { throw new CardsImportException(exception.getMessage()); } } private List<ImportingCard> parserLoyaltyCards(@NonNull @NotNull XmlPullParser parser) throws XmlPullParserException, IOException { parser.nextTag(); parser.require(XmlPullParser.START_TAG, Constant.ELEMENT_NAMESPACE, Constant.LOYALTY_CARDS_ELEMENT); String version = parser.getAttributeValue(Constant.ATTRIBUTE_NAMESPACE, Constant.VERSION_ATTRIBUTE); if (!"1.0".equals(version)) { return null; } List<ImportingCard> cards = new ArrayList<>(); while (true) { CardBuilder cardBuilder = new CardBuilder(); if (parseCard(parser, cardBuilder)) { cards.add(cardBuilder.build()); } else { break; } } parser.require(XmlPullParser.END_TAG, Constant.ELEMENT_NAMESPACE, Constant.LOYALTY_CARDS_ELEMENT); return cards; } private boolean parseCard( @NonNull @NotNull XmlPullParser parser, @NonNull @NotNull CardBuilder cardBuilder) throws XmlPullParserException, IOException { if (XmlPullParser.END_TAG == parser.nextTag()) { return false; } parser.require(XmlPullParser.START_TAG, Constant.ELEMENT_NAMESPACE, Constant.CARD_ELEMENT); final String uid = parser.getAttributeValue(Constant.ATTRIBUTE_NAMESPACE, Constant.UID_ATTRIBUTE); cardBuilder.setUid(UUID.fromString(uid)); while (true) { if (XmlPullParser.END_TAG == parser.nextTag()) { break; } final String name = parser.getName(); if (Constant.NAME_ELEMENT.equals(name)) { cardBuilder.setName(parser.nextText()); } else if (Constant.CODE_ELEMENT.equals(name)) { final String codeTypeUid = parser.getAttributeValue(Constant.ATTRIBUTE_NAMESPACE, Constant.TYPE_UID_ATTRIBUTE); cardBuilder.setCode(parser.nextText()); cardBuilder.setCodeType(UUID.fromString(codeTypeUid)); } else if (Constant.EXTRA_PROPERTIES_ELEMENT.equals(name)) { parseExtraProperties(parser, cardBuilder); } else { throw new RuntimeException("Unknown element " + name); } } parser.require(XmlPullParser.END_TAG, Constant.ELEMENT_NAMESPACE, Constant.CARD_ELEMENT); return true; } private void parseExtraProperties( @NonNull XmlPullParser parser, @NonNull CardBuilder cardBuilder) throws XmlPullParserException, IOException { while (true) { final var propertyBuilder = new ExtraPropertyBuilder(); if (parseExtraProperty(parser, propertyBuilder)) { cardBuilder.addExtraProperty(propertyBuilder.build()); } else { break; } } parser.require(XmlPullParser.END_TAG, Constant.ELEMENT_NAMESPACE, Constant.EXTRA_PROPERTIES_ELEMENT); } private boolean parseExtraProperty( @NonNull XmlPullParser parser, @NonNull ExtraPropertyBuilder propertyBuilder) throws XmlPullParserException, IOException { if (XmlPullParser.START_TAG != parser.nextTag()) { return false; } parser.require(XmlPullParser.START_TAG, Constant.ELEMENT_NAMESPACE, Constant.PROPERTY_ELEMENT); final String uid = parser.getAttributeValue(Constant.ATTRIBUTE_NAMESPACE, Constant.UID_ATTRIBUTE); propertyBuilder.setUid(UUID.fromString(uid)); if (XmlPullParser.START_TAG == parser.nextTag()) { parser.require(XmlPullParser.START_TAG, Constant.ELEMENT_NAMESPACE, Constant.VALUE_ELEMENT); final String valueTypeUid = parser.getAttributeValue(Constant.ATTRIBUTE_NAMESPACE, Constant.TYPE_UID_ATTRIBUTE); final String value = parser.nextText(); propertyBuilder.setValue(value); propertyBuilder.setTypeUid(UUID.fromString(valueTypeUid)); parser.require(XmlPullParser.END_TAG, Constant.ELEMENT_NAMESPACE, Constant.VALUE_ELEMENT); parser.nextTag(); } parser.require(XmlPullParser.END_TAG, Constant.ELEMENT_NAMESPACE, Constant.PROPERTY_ELEMENT); return true; } private void applyCards(List<ImportingCard> importingCards) { final Map<UUID, Card> cardsMap = repository .getAll() .stream() .collect(Collectors.toMap(Card::getUid, card -> card)); for (final ImportingCard importingCard : importingCards) { Card existingCard = cardsMap.get(importingCard.getUid()); if (existingCard == null) { existingCard = new Card(); existingCard.setUid(importingCard.getUid()); existingCard.setName(importingCard.getName()); existingCard.setCode(importingCard.getCode()); existingCard.setCodeFormat(CodeFormat.fromUid(importingCard.getCodeType())); } else { } repository.update(existingCard); } } private static class CardBuilder { private List<ImportingCardExtraProperty> extraProperties; private UUID uid; private String name; private String code; private UUID codeType; public void setUid(@NonNull @NotNull final UUID uid) { this.uid = Objects.requireNonNull(uid); } public void setName(@NonNull @NotNull final String name) { this.name = Objects.requireNonNull(name); } public void setCode(@NonNull @NotNull final String code) { this.code = Objects.requireNonNull(code); } public void setCodeType(@NonNull @NotNull final UUID codeType) { this.codeType = codeType; } public void addExtraProperty(@NonNull final ImportingCardExtraProperty property) { if (extraProperties == null) { extraProperties = new ArrayList<>(); } extraProperties.add(property); } public ImportingCard build() { return new ImportingCard(uid, name, code, codeType, extraProperties); } } private static class ExtraPropertyBuilder { private UUID uid; private String value; private UUID typeUid; public void setUid(@NotNull final UUID uid) { this.uid = uid; } public void setTypeUid(@NotNull final UUID typeUid) { this.typeUid = typeUid; } public void setValue(@NotNull final String value) { this.value = value; } public ImportingCardExtraProperty build() { return new ImportingCardExtraProperty(uid, value, typeUid); } } }