19784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar/* 29784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * Copyright (C) 2015 The Android Open Source Project 39784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * 49784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 59784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * you may not use this file except in compliance with the License. 69784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * You may obtain a copy of the License at 79784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * 89784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 99784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * 109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * Unless required by applicable law or agreed to in writing, software 119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * See the License for the specific language governing permissions and 149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * limitations under the License. 159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar */ 169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarpackage android.databinding.tool; 189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport org.apache.commons.io.IOUtils; 209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.processing.Scope; 229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.processing.ScopedException; 239784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.util.L; 249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.util.Preconditions; 259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.writer.JavaFileWriter; 269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.io.File; 289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.io.FileInputStream; 299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.io.FileNotFoundException; 309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.io.FileOutputStream; 319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.io.IOException; 329784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.io.InputStream; 339784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.util.ArrayList; 349784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.util.HashMap; 359784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.util.List; 369784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.util.Map; 379784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.util.Properties; 389784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 399784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 409784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar/** 419784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * This class is used by Android Gradle plugin. 429784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar */ 439784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar@SuppressWarnings("unused") 449784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarpublic class DataBindingBuilder { 459784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Versions mVersions; 469784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final static String EXCLUDE_PATTERN = "android/databinding/layouts/*.*"; 479784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public String getCompilerVersion() { 489784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return getVersions().compiler; 499784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 509784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public String getBaseLibraryVersion(String compilerVersion) { 529784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return getVersions().baseLibrary; 539784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 549784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 559784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public String getLibraryVersion(String compilerVersion) { 569784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return getVersions().extensions; 579784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public String getBaseAdaptersVersion(String compilerVersion) { 609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return getVersions().extensions; 619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void setPrintMachineReadableOutput(boolean machineReadableOutput) { 649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ScopedException.encodeOutput(machineReadableOutput); 659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean getPrintMachineReadableOutput() { 689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return ScopedException.issEncodeOutput(); 699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void setDebugLogEnabled(boolean enableDebugLogs) { 729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar L.setDebugLog(enableDebugLogs); 739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean isDebugLogEnabled() { 769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return L.isDebugEnabled(); 779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private Versions getVersions() { 809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (mVersions != null) { 819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mVersions; 829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar try { 849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Properties props = new Properties(); 859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar InputStream stream = getClass().getResourceAsStream("/data_binding_version_info.properties"); 869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar try { 879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar props.load(stream); 889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mVersions = new Versions(props); 899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } finally { 909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOUtils.closeQuietly(stream); 919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } catch (IOException exception) { 939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar L.e(exception, "Cannot read data binding version"); 949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mVersions; 969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 979784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar /** 999784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * Returns the list of classes that should be excluded from package task 1009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * 1019784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * @param layoutXmlProcessor The LayoutXmlProcessor for this variant 1029784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * @param generatedClassListFile The location of the File into which data binding compiler wrote 1039784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * list of generated classes 1049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * 1059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * @return The list of classes to exclude. They are already in JNI format. 1069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar */ 1079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public List<String> getJarExcludeList(LayoutXmlProcessor layoutXmlProcessor, 1089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File generatedClassListFile) { 1099784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<String> excludes = new ArrayList<String>(); 1109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String appPkgAsClass = layoutXmlProcessor.getPackage().replace('.', '/'); 1119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String infoClassAsClass = layoutXmlProcessor.getInfoClassFullName().replace('.', '/'); 1129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1139784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar excludes.add(infoClassAsClass + ".class"); 1149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar excludes.add(EXCLUDE_PATTERN); 1159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar excludes.add(appPkgAsClass + "/BR.*"); 1169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar excludes.add("android/databinding/DynamicUtil.class"); 1179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (generatedClassListFile != null) { 1189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<String> generatedClasses = readGeneratedClasses(generatedClassListFile); 1199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (String klass : generatedClasses) { 1209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar excludes.add(klass.replace('.', '/') + ".class"); 1219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1239784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Scope.assertNoError(); 1249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return excludes; 1259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<String> readGeneratedClasses(File generatedClassListFile) { 1289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.checkNotNull(generatedClassListFile, "Data binding exclude generated task" 1299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar + " is not configured properly"); 1309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.check(generatedClassListFile.exists(), 1319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar "Generated class list does not exist %s", generatedClassListFile.getAbsolutePath()); 1329784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileInputStream fis = null; 1339784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar try { 1349784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar fis = new FileInputStream(generatedClassListFile); 1359784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return IOUtils.readLines(fis); 1369784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } catch (FileNotFoundException e) { 1379784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar L.e(e, "Unable to read generated class list from %s", 1389784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar generatedClassListFile.getAbsoluteFile()); 1399784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } catch (IOException e) { 1409784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar L.e(e, "Unexpected exception while reading %s", 1419784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar generatedClassListFile.getAbsoluteFile()); 1429784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } finally { 1439784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOUtils.closeQuietly(fis); 1449784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1459784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar L.e("Could not read data binding generated class list"); 1469784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return null; 1479784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1489784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1499784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public JavaFileWriter createJavaFileWriter(File outFolder) { 1509784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return new GradleFileWriter(outFolder.getAbsolutePath()); 1519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1529784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1539784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar static class GradleFileWriter extends JavaFileWriter { 1549784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1559784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final String outputBase; 1569784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1579784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public GradleFileWriter(String outputBase) { 1589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar this.outputBase = outputBase; 1599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void writeToFile(String canonicalName, String contents) { 1639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String asPath = canonicalName.replace('.', '/'); 1649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File f = new File(outputBase + "/" + asPath + ".java"); 1659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar //noinspection ResultOfMethodCallIgnored 1669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar f.getParentFile().mkdirs(); 1679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileOutputStream fos = null; 1689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar try { 1699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar fos = new FileOutputStream(f); 1709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOUtils.write(contents, fos); 1719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } catch (IOException e) { 1729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar L.e(e, "cannot write file " + f.getAbsolutePath()); 1739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } finally { 1749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOUtils.closeQuietly(fos); 1759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static class Versions { 1809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String compilerCommon; 1819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String compiler; 1829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String baseLibrary; 1839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String extensions; 1849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public Versions(Properties properties) { 1869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar compilerCommon = properties.getProperty("compilerCommon"); 1879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar compiler = properties.getProperty("compiler"); 1889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar baseLibrary = properties.getProperty("baseLibrary"); 1899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar extensions = properties.getProperty("extensions"); 1909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.checkNotNull(compilerCommon, "cannot read compiler common version"); 1919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.checkNotNull(compiler, "cannot read compiler version"); 1929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.checkNotNull(baseLibrary, "cannot read baseLibrary version"); 1939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.checkNotNull(extensions, "cannot read extensions version"); 1949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar}