001/* 002 * MIT License 003 * 004 * Copyright (c) 2016 Michael Angstadt 005 * 006 * Permission is hereby granted, free of charge, to any person obtaining a copy 007 * of this software and associated documentation files (the "Software"), to deal 008 * in the Software without restriction, including without limitation the rights 009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 010 * copies of the Software, and to permit persons to whom the Software is 011 * furnished to do so, subject to the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be included in 014 * all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 022 * SOFTWARE. 023 */ 024 025package com.github.mangstadt.vinnie.io; 026 027import java.util.HashMap; 028import java.util.Map; 029 030import com.github.mangstadt.vinnie.SyntaxStyle; 031 032/** 033 * Defines a set of rules that determine what kind of syntax the vobject data 034 * stream uses. 035 * @author Michael Angstadt 036 */ 037public class SyntaxRules { 038 private SyntaxStyle defaultSyntaxStyle; 039 private final Map<String, Map<String, SyntaxStyle>> syntaxRules = new HashMap<String, Map<String, SyntaxStyle>>(); 040 041 /** 042 * Creates a new set of syntax rules. 043 * @param defaultSyntaxStyle the syntax style to use when it can't be 044 * determined what the data stream uses 045 */ 046 public SyntaxRules(SyntaxStyle defaultSyntaxStyle) { 047 this.defaultSyntaxStyle = defaultSyntaxStyle; 048 } 049 050 /** 051 * Gets the the syntax style to use when it can't be determined what the 052 * data stream uses. 053 * @return the default syntax style 054 */ 055 public SyntaxStyle getDefaultSyntaxStyle() { 056 return defaultSyntaxStyle; 057 } 058 059 /** 060 * Sets the syntax style to use when it can't be determined what the data 061 * stream uses. 062 * @param defaultSyntaxStyle the default syntax style (cannot be null) 063 */ 064 public void setDefaultSyntaxStyle(SyntaxStyle defaultSyntaxStyle) { 065 this.defaultSyntaxStyle = defaultSyntaxStyle; 066 } 067 068 /** 069 * Determines if this object contains rules for the given component. 070 * @param component the component name (e.g. "VCARD") 071 * @return true if this component has syntax rules, false if not 072 */ 073 public boolean hasSyntaxRules(String component) { 074 if (component != null) { 075 component = component.toUpperCase(); 076 } 077 return syntaxRules.containsKey(component); 078 } 079 080 /** 081 * Gets the syntax style to use for a given component. 082 * @param component the component name (e.g. "VCARD") 083 * @param versionValue the value of the component's VERSION property (e.g. 084 * "2.1") 085 * @return the syntax style or null if none was found 086 */ 087 public SyntaxStyle getSyntaxStyle(String component, String versionValue) { 088 component = (component == null) ? null : component.toUpperCase(); 089 Map<String, SyntaxStyle> rules = syntaxRules.get(component); 090 return (rules == null) ? null : rules.get(versionValue); 091 } 092 093 /** 094 * Adds a rule. 095 * @param component the name of the component that contains the VERSION 096 * property (e.g. "VCARD"), or null if the VERSION property will not be 097 * inside of any components 098 * @param version the value of the VERSION property 099 * @param syntaxStyle the syntax style to use when a VERSION property with 100 * the given value, and under the given component, is encountered 101 */ 102 public void addRule(String component, String version, SyntaxStyle syntaxStyle) { 103 component = (component == null) ? null : component.toUpperCase(); 104 105 Map<String, SyntaxStyle> rules = syntaxRules.get(component); 106 if (rules == null) { 107 rules = new HashMap<String, SyntaxStyle>(); 108 syntaxRules.put(component, rules); 109 } 110 111 rules.put(version, syntaxStyle); 112 } 113 114 /** 115 * Creates a set of rules for iCalendar data. 116 * @return the rules 117 */ 118 public static SyntaxRules iCalendar() { 119 /* 120 * Initialize to the old style syntax because the VERSION property can 121 * technically exist anywhere inside the data stream under this version. 122 * 123 * However, this setting is rarely important in practice because I've 124 * never seen an iCalendar object that doesn't put its VERSION property 125 * at the very beginning. 126 */ 127 SyntaxRules rules = new SyntaxRules(SyntaxStyle.OLD); 128 String component = "VCALENDAR"; 129 rules.addRule(component, "1.0", SyntaxStyle.OLD); 130 rules.addRule(component, "2.0", SyntaxStyle.NEW); 131 return rules; 132 } 133 134 /** 135 * Creates a set of rules for vCard data. 136 * @return the rules 137 */ 138 public static SyntaxRules vcard() { 139 /* 140 * Initialize to the old style syntax because the VERSION property can 141 * technically exist anywhere inside the data stream under this version. 142 * 143 * However, this setting is rarely important in practice because I've 144 * never seen a vCard that doesn't put its VERSION property at the very 145 * beginning. 146 */ 147 SyntaxRules rules = new SyntaxRules(SyntaxStyle.OLD); 148 String component = "VCARD"; 149 rules.addRule(component, "2.1", SyntaxStyle.OLD); 150 rules.addRule(component, "3.0", SyntaxStyle.NEW); 151 rules.addRule(component, "4.0", SyntaxStyle.NEW); 152 return rules; 153 } 154}